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 }