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