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