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