1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.plugin.eclipse.writers;
20
21 import java.io.File;
22 import java.io.FileOutputStream;
23 import java.io.IOException;
24 import java.io.OutputStreamWriter;
25 import java.io.Writer;
26 import java.util.ArrayList;
27 import java.util.HashMap;
28 import java.util.HashSet;
29 import java.util.Iterator;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.Set;
33
34 import org.apache.maven.plugin.MojoExecutionException;
35 import org.apache.maven.plugin.eclipse.BuildCommand;
36 import org.apache.maven.plugin.eclipse.Constants;
37 import org.apache.maven.plugin.eclipse.EclipseSourceDir;
38 import org.apache.maven.plugin.eclipse.Messages;
39 import org.apache.maven.plugin.ide.IdeDependency;
40 import org.apache.maven.plugin.ide.IdeUtils;
41 import org.codehaus.plexus.util.IOUtil;
42 import org.codehaus.plexus.util.StringUtils;
43 import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter;
44 import org.codehaus.plexus.util.xml.XMLWriter;
45
46
47
48
49
50
51
52
53
54 public class EclipseClasspathWriter
55 extends AbstractEclipseWriter
56 {
57
58
59
60
61 private static final String ORG_ECLIPSE_AJDT_INPATH = "org.eclipse.ajdt.inpath";
62
63
64
65
66 private static final String ORG_ECLIPSE_AJDT_ASPECTPATH = "org.eclipse.ajdt.aspectpath";
67
68 private static final String ASPECTJRT_CONTAINER = "org.eclipse.ajdt.core.ASPECTJRT_CONTAINER";
69
70
71
72
73 private static final String NAME = "name";
74
75
76
77
78 private static final String VALUE = "value";
79
80
81
82
83 private static final String ATTRIBUTE = "attribute";
84
85
86
87
88 private static final String ATTRIBUTES = "attributes";
89
90
91
92
93 protected static final String M2_REPO = "M2_REPO";
94
95
96
97
98 private static final String ATTR_SOURCEPATH = "sourcepath";
99
100
101
102
103 private static final String ATTR_OUTPUT = "output";
104
105
106
107
108 private static final String ATTR_PATH = "path";
109
110
111
112
113 private static final String ATTR_KIND = "kind";
114
115
116
117
118 private static final String ATTR_VAR = "var";
119
120
121
122
123 private static final String ATTR_LIB = "lib";
124
125
126
127
128 private static final String ATTR_SRC = "src";
129
130
131
132
133 private static final String ATTR_INCLUDING = "including";
134
135
136
137
138 private static final String ATTR_EXCLUDING = "excluding";
139
140
141
142
143 private static final String ELT_CLASSPATHENTRY = "classpathentry";
144
145
146
147
148 private static final String ELT_CLASSPATH = "classpath";
149
150
151
152
153 private static final String FILE_DOT_CLASSPATH = ".classpath";
154
155
156
157
158 public void write()
159 throws MojoExecutionException
160 {
161
162 Writer w;
163
164 try
165 {
166 w =
167 new OutputStreamWriter( new FileOutputStream( new File( config.getEclipseProjectDirectory(),
168 FILE_DOT_CLASSPATH ) ), "UTF-8" );
169 }
170 catch ( IOException ex )
171 {
172 throw new MojoExecutionException( Messages.getString( "EclipsePlugin.erroropeningfile" ), ex );
173 }
174
175 XMLWriter writer = new PrettyPrintXMLWriter( w, "UTF-8", null );
176
177 writer.startElement( ELT_CLASSPATH );
178
179 String defaultOutput =
180 IdeUtils.toRelativeAndFixSeparator( config.getProjectBaseDir(), config.getBuildOutputDirectory(), false );
181
182
183
184
185
186
187 List specialSources = new ArrayList();
188
189
190 Map byOutputDir = new HashMap();
191
192 for ( int j = 0; j < config.getSourceDirs().length; j++ )
193 {
194 EclipseSourceDir dir = config.getSourceDirs()[j];
195
196
197 List byOutputDirs = (List) byOutputDir.get( dir.getOutput() );
198 if ( byOutputDirs == null )
199 {
200
201 byOutputDir.put( dir.getOutput() == null ? defaultOutput : dir.getOutput(), byOutputDirs =
202 new ArrayList() );
203 }
204 byOutputDirs.add( dir );
205 }
206
207 for ( int j = 0; j < config.getSourceDirs().length; j++ )
208 {
209 EclipseSourceDir dir = config.getSourceDirs()[j];
210
211 log.debug( "Processing classpath for: " + dir.toString() + "; default output=" + defaultOutput );
212
213 boolean isSpecial = false;
214
215
216 if ( dir.isResource() )
217 {
218
219
220
221 if ( dir.getOutput() != null
222 && !dir.getOutput().equals( defaultOutput )
223 && dir.getOutput().startsWith( defaultOutput )
224 && byOutputDir.get( defaultOutput ) != null
225 && !( (List) byOutputDir.get( defaultOutput ) ).isEmpty()
226 )
227 {
228
229
230
231 log.debug( "Marking as special to prevent output folder nesting: " + dir.getPath() + " (output="
232 + dir.getOutput() + ")" );
233
234 isSpecial = true;
235 specialSources.add( dir );
236 }
237 }
238
239 writer.startElement( ELT_CLASSPATHENTRY );
240
241 writer.addAttribute( ATTR_KIND, "src" );
242 writer.addAttribute( ATTR_PATH, dir.getPath() );
243
244 if ( !isSpecial && dir.getOutput() != null && !defaultOutput.equals( dir.getOutput() ) )
245 {
246 writer.addAttribute( ATTR_OUTPUT, dir.getOutput() );
247 }
248
249 String includes = dir.getIncludeAsString();
250 if ( StringUtils.isNotEmpty( includes ) )
251 {
252 writer.addAttribute( ATTR_INCLUDING, includes );
253 }
254
255 String excludes = dir.getExcludeAsString();
256 if ( StringUtils.isNotEmpty( excludes ) )
257 {
258 writer.addAttribute( ATTR_EXCLUDING, excludes );
259 }
260
261 writer.endElement();
262
263 }
264
265
266 if ( !specialSources.isEmpty() )
267 {
268 log.info( "Creating maven-eclipse.xml Ant file to handle resources" );
269
270 try
271 {
272 Writer buildXmlWriter =
273 new OutputStreamWriter( new FileOutputStream( new File( config.getEclipseProjectDirectory(),
274 "maven-eclipse.xml" ) ), "UTF-8" );
275 PrettyPrintXMLWriter buildXmlPrinter = new PrettyPrintXMLWriter( buildXmlWriter );
276
277 buildXmlPrinter.startElement( "project" );
278 buildXmlPrinter.addAttribute( "default", "copy-resources" );
279
280 buildXmlPrinter.startElement( "target" );
281 buildXmlPrinter.addAttribute( NAME, "init" );
282
283 buildXmlPrinter.endElement();
284
285 buildXmlPrinter.startElement( "target" );
286 buildXmlPrinter.addAttribute( NAME, "copy-resources" );
287 buildXmlPrinter.addAttribute( "depends", "init" );
288
289 for ( Iterator it = specialSources.iterator(); it.hasNext(); )
290 {
291
292
293 EclipseSourceDir dir = (EclipseSourceDir) it.next();
294 buildXmlPrinter.startElement( "copy" );
295 buildXmlPrinter.addAttribute( "todir", dir.getOutput() );
296 buildXmlPrinter.addAttribute( "filtering", "" + dir.isFiltering() );
297
298 buildXmlPrinter.startElement( "fileset" );
299 buildXmlPrinter.addAttribute( "dir", dir.getPath() );
300 if ( dir.getIncludeAsString() != null )
301 {
302 buildXmlPrinter.addAttribute( "includes", dir.getIncludeAsString() );
303 }
304 if ( dir.getExcludeAsString() != null )
305 {
306 buildXmlPrinter.addAttribute( "excludes", dir.getExcludeAsString() );
307 }
308 buildXmlPrinter.endElement();
309
310 buildXmlPrinter.endElement();
311 }
312
313 buildXmlPrinter.endElement();
314
315 buildXmlPrinter.endElement();
316
317 IOUtil.close( buildXmlWriter );
318 }
319 catch ( IOException e )
320 {
321 throw new MojoExecutionException( "Cannot create " + config.getEclipseProjectDirectory()
322 + "/maven-eclipse.xml", e );
323 }
324
325 log.info( "Creating external launcher file" );
326
327 new EclipseAntExternalLaunchConfigurationWriter().init( log, config, "Maven_Ant_Builder.launch",
328 "maven-eclipse.xml" ).write();
329
330
331
332 config.getBuildCommands().add(
333 new BuildCommand(
334 "org.eclipse.ui.externaltools.ExternalToolBuilder",
335 "LaunchConfigHandle",
336 "<project>/"
337 + EclipseLaunchConfigurationWriter.FILE_DOT_EXTERNAL_TOOL_BUILDERS
338 + "Maven_Ant_Builder.launch" ) );
339 }
340
341
342
343
344
345 writer.startElement( ELT_CLASSPATHENTRY );
346 writer.addAttribute( ATTR_KIND, ATTR_OUTPUT );
347 writer.addAttribute( ATTR_PATH, defaultOutput );
348 writer.endElement();
349
350 Set addedDependencies = new HashSet();
351
352
353
354
355
356 IdeDependency[] depsToWrite = config.getDeps();
357 for ( int j = 0; j < depsToWrite.length; j++ )
358 {
359 IdeDependency dep = depsToWrite[j];
360 if ( dep.isJavaApi() )
361 {
362 String depId = getDependencyId( dep );
363 if ( !addedDependencies.contains( depId ) )
364 {
365 addDependency( writer, dep );
366 addedDependencies.add( depId );
367 }
368 }
369 }
370
371
372 if (!config.isClasspathContainersLast())
373 {
374 writeClasspathContainers(writer);
375 }
376
377
378
379
380 for ( int j = 0; j < depsToWrite.length; j++ )
381 {
382 IdeDependency dep = depsToWrite[j];
383
384 if ( dep.isAddedToClasspath() )
385 {
386 String depId = getDependencyId( dep );
387
388 if ( !addedDependencies.contains( depId ) )
389 {
390 addDependency( writer, dep );
391 addedDependencies.add( depId );
392 }
393 }
394 }
395
396 if (config.isClasspathContainersLast())
397 {
398 writeClasspathContainers(writer);
399 }
400
401 writer.endElement();
402
403 IOUtil.close( w );
404
405 }
406
407
408
409
410 private void writeClasspathContainers(XMLWriter writer)
411 {
412
413
414
415
416 for ( Iterator it = config.getClasspathContainers().iterator(); it.hasNext(); )
417 {
418 writer.startElement( ELT_CLASSPATHENTRY );
419 writer.addAttribute( ATTR_KIND, "con" );
420 writer.addAttribute( ATTR_PATH, (String) it.next() );
421 writer.endElement();
422 }
423 }
424
425 private String getDependencyId( IdeDependency dep )
426 {
427 String depId =
428 dep.getGroupId() + ":" + dep.getArtifactId() + ":" + dep.getClassifier() + ":" + dep.getVersion();
429
430 if ( dep.isReferencedProject() )
431 {
432
433 depId = dep.getEclipseProjectName();
434 }
435 return depId;
436 }
437
438 protected void addDependency( XMLWriter writer, IdeDependency dep )
439 throws MojoExecutionException
440 {
441
442 String path;
443 String kind;
444 String sourcepath = null;
445 String javadocpath = null;
446
447 if ( dep.isReferencedProject() && !config.isPde() )
448 {
449 path = "/" + dep.getEclipseProjectName();
450 kind = ATTR_SRC;
451 }
452 else if ( dep.isReferencedProject() && config.isPde() )
453 {
454
455 return;
456 }
457 else
458 {
459 File artifactPath = dep.getFile();
460
461 if ( artifactPath == null )
462 {
463 log.error( Messages.getString( "EclipsePlugin.artifactpathisnull", dep.getId() ) );
464 return;
465 }
466
467 if ( dep.isSystemScoped() )
468 {
469 path = IdeUtils.toRelativeAndFixSeparator( config.getEclipseProjectDirectory(), artifactPath, false );
470
471 if ( log.isDebugEnabled() )
472 {
473 log.debug( Messages.getString( "EclipsePlugin.artifactissystemscoped",
474 new Object[] { dep.getArtifactId(), path } ) );
475 }
476
477 kind = ATTR_LIB;
478 }
479 else
480 {
481 File localRepositoryFile = new File( config.getLocalRepository().getBasedir() );
482
483
484
485 if ( config.isPde() && ( dep.isProvided() || dep.isOsgiBundle() ) )
486 {
487 return;
488 }
489 else if ( config.isPde() && !dep.isProvided() && !dep.isTestDependency() )
490 {
491
492 path = dep.getFile().getName();
493
494 kind = ATTR_LIB;
495 }
496
497
498 else
499 {
500 String fullPath = artifactPath.getPath();
501 String relativePath =
502 IdeUtils.toRelativeAndFixSeparator( localRepositoryFile, new File( fullPath ), false );
503
504 if ( !new File( relativePath ).isAbsolute() )
505 {
506 path = M2_REPO + "/"
507 + relativePath;
508 kind = ATTR_VAR;
509 }
510 else
511 {
512 path = relativePath;
513 kind = ATTR_LIB;
514 }
515 }
516
517 if ( dep.getSourceAttachment() != null )
518 {
519 if ( ATTR_VAR.equals( kind ) )
520 {
521 sourcepath =
522 M2_REPO
523 + "/"
524 + IdeUtils.toRelativeAndFixSeparator( localRepositoryFile, dep.getSourceAttachment(),
525 false );
526 }
527 else
528 {
529
530 sourcepath = IdeUtils.getCanonicalPath( dep.getSourceAttachment() );
531 }
532 }
533
534 if ( dep.getJavadocAttachment() != null )
535 {
536
537
538 javadocpath = IdeUtils.fixSeparator( IdeUtils.getCanonicalPath( dep.getJavadocAttachment() ) );
539 }
540
541 }
542
543 }
544
545
546 if ( ( config.getAjdtVersion() != 0 ) && isAspectJRuntime( dep ) )
547 {
548 if ( ! config.getClasspathContainers().contains( ASPECTJRT_CONTAINER ) )
549 {
550 config.getClasspathContainers().add( ASPECTJRT_CONTAINER );
551 }
552 return;
553 }
554
555 writer.startElement( ELT_CLASSPATHENTRY );
556 writer.addAttribute( ATTR_KIND, kind );
557 writer.addAttribute( ATTR_PATH, path );
558
559 if ( sourcepath != null )
560 {
561 writer.addAttribute( ATTR_SOURCEPATH, sourcepath );
562 }
563
564 boolean attributeElemOpen = false;
565
566 if ( javadocpath != null )
567 {
568 if ( !attributeElemOpen )
569 {
570 writer.startElement( ATTRIBUTES );
571 attributeElemOpen = true;
572 }
573
574 writer.startElement( ATTRIBUTE );
575 writer.addAttribute( VALUE, "jar:" + new File( javadocpath ).toURI() + "!/" );
576 writer.addAttribute( NAME, "javadoc_location" );
577 writer.endElement();
578
579 }
580
581 if ( Constants.PROJECT_PACKAGING_WAR.equals( this.config.getPackaging() ) && config.getWtpapplicationxml()
582 && kind.equals( ATTR_VAR ) && !dep.isTestDependency() && !dep.isProvided()
583 && !dep.isSystemScopedOutsideProject( this.config.getProject() ) )
584 {
585 if ( !attributeElemOpen )
586 {
587 writer.startElement( ATTRIBUTES );
588 attributeElemOpen = true;
589 }
590
591 writer.startElement( ATTRIBUTE );
592 writer.addAttribute( VALUE, "/WEB-INF/lib" );
593 writer.addAttribute( NAME, "org.eclipse.jst.component.dependency" );
594 writer.endElement();
595
596 }
597
598 if ( dep.isAjdtDependency() && ( config.getAjdtVersion() >= 1.5 ) )
599 {
600 if ( !attributeElemOpen )
601 {
602 writer.startElement( ATTRIBUTES );
603 attributeElemOpen = true;
604 }
605
606 writer.startElement( ATTRIBUTE );
607 writer.addAttribute( NAME, ORG_ECLIPSE_AJDT_ASPECTPATH );
608 writer.addAttribute( VALUE, Boolean.TRUE.toString() );
609 writer.endElement();
610
611 }
612
613 if ( dep.isAjdtWeaveDependency() && ( config.getAjdtVersion() >= 1.5 ) )
614 {
615 if ( !attributeElemOpen )
616 {
617 writer.startElement( ATTRIBUTES );
618 attributeElemOpen = true;
619 }
620
621 writer.startElement( ATTRIBUTE );
622 writer.addAttribute( NAME, ORG_ECLIPSE_AJDT_INPATH );
623 writer.addAttribute( VALUE, Boolean.TRUE.toString() );
624 writer.endElement();
625
626 }
627
628 if ( attributeElemOpen )
629 {
630 writer.endElement();
631 }
632 writer.endElement();
633
634 }
635
636
637
638
639 private boolean isAspectJRuntime( IdeDependency dep )
640 {
641 if ( dep.getArtifactId().equals( "aspectjrt" ) )
642 {
643 return dep.getGroupId().equals( "org.aspectj" ) || dep.getGroupId().equals( "aspectj" );
644 }
645 return false;
646 }
647 }