View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.plugin.eclipse.writers;
20  
21  import java.io.File;
22  import java.io.FileInputStream;
23  import java.io.FileOutputStream;
24  import java.io.IOException;
25  import java.io.InputStreamReader;
26  import java.io.OutputStreamWriter;
27  import java.io.Reader;
28  import java.io.Writer;
29  import java.util.ArrayList;
30  import java.util.Iterator;
31  import java.util.LinkedHashSet;
32  import java.util.List;
33  import java.util.Set;
34  
35  import org.apache.maven.model.Resource;
36  import org.apache.maven.plugin.MojoExecutionException;
37  import org.apache.maven.plugin.eclipse.BuildCommand;
38  import org.apache.maven.plugin.eclipse.LinkedResource;
39  import org.apache.maven.plugin.eclipse.Messages;
40  import org.apache.maven.plugin.ide.IdeDependency;
41  import org.apache.maven.plugin.ide.IdeUtils;
42  import org.codehaus.plexus.util.IOUtil;
43  import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter;
44  import org.codehaus.plexus.util.xml.XMLWriter;
45  import org.codehaus.plexus.util.xml.Xpp3Dom;
46  import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
47  import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
48  
49  /**
50   * Writes eclipse .project file.
51   * 
52   * @author <a href="mailto:trygvis@inamo.no">Trygve Laugst&oslash;l</a>
53   * @author <a href="mailto:kenney@neonics.com">Kenney Westerhof</a>
54   * @author <a href="mailto:fgiust@apache.org">Fabrizio Giustina</a>
55   * @version $Id: EclipseProjectWriter.java 1185446 2011-10-18 01:00:41Z baerrach $
56   */
57  public class EclipseProjectWriter
58      extends AbstractEclipseWriter
59  {
60      private static final String ELT_NAME = "name"; //$NON-NLS-1$
61  
62      private static final String ELT_COMMENT = "comment"; //$NON-NLS-1$
63  
64      private static final String ELT_BUILD_COMMAND = "buildCommand"; //$NON-NLS-1$
65  
66      private static final String ELT_LINK = "link"; //$NON-NLS-1$
67  
68      private static final String ELT_BUILD_SPEC = "buildSpec"; //$NON-NLS-1$
69  
70      private static final String ELT_LINKED_RESOURCES = "linkedResources"; //$NON-NLS-1$
71  
72      private static final String ELT_NATURE = "nature"; //$NON-NLS-1$
73  
74      private static final String ELT_NATURES = "natures"; //$NON-NLS-1$
75  
76      private static final String FILE_DOT_PROJECT = ".project"; //$NON-NLS-1$
77  
78      /**
79       * Constant for links to files.
80       */
81      private static final int LINK_TYPE_FILE = 1;
82  
83      /**
84       * Constant for links to directories.
85       */
86      private static final int LINK_TYPE_DIRECTORY = 2;
87  
88      /**
89       * To Store the link names
90       */
91      ArrayList linkNames = new ArrayList();
92  
93      /**
94       * @see org.apache.maven.plugin.eclipse.writers.EclipseWriter#write()
95       */
96      public void write()
97          throws MojoExecutionException
98      {
99  
100         Set projectnatures = new LinkedHashSet();
101         Set buildCommands = new LinkedHashSet();
102         Set linkedResources = new LinkedHashSet();
103 
104         File dotProject = new File( config.getEclipseProjectDirectory(), FILE_DOT_PROJECT );
105 
106         if ( dotProject.exists() )
107         {
108 
109             log.info( Messages.getString( "EclipsePlugin.keepexisting", dotProject.getAbsolutePath() ) ); //$NON-NLS-1$
110 
111             // parse existing file in order to keep manually-added entries
112             Reader reader = null;
113             try
114             {
115                 reader = new InputStreamReader( new FileInputStream( dotProject ), "UTF-8" );
116                 Xpp3Dom dom = Xpp3DomBuilder.build( reader );
117 
118                 Xpp3Dom naturesElement = dom.getChild( ELT_NATURES );
119                 if ( naturesElement != null )
120                 {
121                     Xpp3Dom[] existingNatures = naturesElement.getChildren( ELT_NATURE );
122                     for ( int j = 0; j < existingNatures.length; j++ )
123                     {
124                         // adds all the existing natures
125                         projectnatures.add( existingNatures[j].getValue() );
126                     }
127                 }
128 
129                 Xpp3Dom buildSpec = dom.getChild( ELT_BUILD_SPEC );
130                 if ( buildSpec != null )
131                 {
132                     Xpp3Dom[] existingBuildCommands = buildSpec.getChildren( ELT_BUILD_COMMAND );
133                     for ( int j = 0; j < existingBuildCommands.length; j++ )
134                     {
135                         Xpp3Dom buildCommandName = existingBuildCommands[j].getChild( ELT_NAME );
136                         if ( buildCommandName != null )
137                         {
138                             buildCommands.add( new BuildCommand( existingBuildCommands[j] ) );
139                         }
140                     }
141                 }
142                 // Added the below code to preserve the Symbolic links
143                 Xpp3Dom linkedResourcesElement = dom.getChild( ELT_LINKED_RESOURCES );
144                 if ( linkedResourcesElement != null )
145                 {
146                     Xpp3Dom[] existingLinks = linkedResourcesElement.getChildren( ELT_LINK );
147                     for ( int j = 0; j < existingLinks.length; j++ )
148                     {
149                         Xpp3Dom linkName = existingLinks[j].getChild( ELT_NAME );
150                         if ( linkName != null )
151                         {
152                             // add all the existing symbolic links
153                             linkNames.add( existingLinks[j].getChild( ELT_NAME ).getValue() );
154                             linkedResources.add( new LinkedResource( existingLinks[j] ) );
155                         }
156                     }
157                 }
158 
159             }
160             catch ( XmlPullParserException e )
161             {
162                 log.warn( Messages.getString( "EclipsePlugin.cantparseexisting", dotProject.getAbsolutePath() ) ); //$NON-NLS-1$
163             }
164             catch ( IOException e )
165             {
166                 log.warn( Messages.getString( "EclipsePlugin.cantparseexisting", dotProject.getAbsolutePath() ) ); //$NON-NLS-1$
167             }
168             finally
169             {
170                 IOUtil.close( reader );
171             }
172         }
173 
174         // adds new entries after the existing ones
175         for ( Iterator iter = config.getProjectnatures().iterator(); iter.hasNext(); )
176         {
177             projectnatures.add( iter.next() );
178         }
179 
180         for ( Iterator iter = config.getBuildCommands().iterator(); iter.hasNext(); )
181         {
182             buildCommands.add( (BuildCommand) iter.next() );
183         }
184 
185         for ( Iterator iter = config.getLinkedResources().iterator(); iter.hasNext(); )
186         {
187             linkedResources.add( (LinkedResource) iter.next() );
188         }
189 
190         Writer w;
191 
192         try
193         {
194             w = new OutputStreamWriter( new FileOutputStream( dotProject ), "UTF-8" );
195         }
196         catch ( IOException ex )
197         {
198             throw new MojoExecutionException( Messages.getString( "EclipsePlugin.erroropeningfile" ), ex ); //$NON-NLS-1$
199         }
200 
201         XMLWriter writer = new PrettyPrintXMLWriter( w, "UTF-8", null );
202 
203         writer.startElement( "projectDescription" ); //$NON-NLS-1$
204 
205         writer.startElement( ELT_NAME );
206         writer.writeText( config.getEclipseProjectName() );
207         writer.endElement();
208 
209         addComment( writer, config.getProject().getDescription() );
210 
211         writer.startElement( "projects" ); //$NON-NLS-1$
212 
213         IdeDependency[] dependencies = config.getDeps();
214         
215         // referenced projects should not be added for plugins
216         if ( !config.isPde() )
217         {
218             List duplicates = new ArrayList();
219             for ( int j = 0; j < dependencies.length; j++ )
220             {
221                 IdeDependency dep = dependencies[j];
222                 // Avoid duplicates entries when same project is refered using multiple types
223                 // (ejb, test-jar ...)
224                 if ( dep.isReferencedProject() && !duplicates.contains( dep.getEclipseProjectName() ) )
225                 {
226                     writer.startElement( "project" ); //$NON-NLS-1$
227                     writer.writeText( dep.getEclipseProjectName() );
228                     writer.endElement();
229                     duplicates.add( dep.getEclipseProjectName() );
230                 }
231             }
232         }
233 
234         writer.endElement(); // projects
235 
236         writer.startElement( ELT_BUILD_SPEC );
237 
238         for ( Iterator it = buildCommands.iterator(); it.hasNext(); )
239         {
240             ( (BuildCommand) it.next() ).print( writer );
241         }
242 
243         writer.endElement(); // buildSpec
244 
245         writer.startElement( ELT_NATURES );
246 
247         for ( Iterator it = projectnatures.iterator(); it.hasNext(); )
248         {
249             writer.startElement( ELT_NATURE );
250             writer.writeText( (String) it.next() );
251             writer.endElement(); // name
252         }
253 
254         writer.endElement(); // natures
255 
256         boolean addLinks = !config.getProjectBaseDir().equals( config.getEclipseProjectDirectory() );
257 
258         if ( addLinks || ( config.isPde() && dependencies.length > 0 ) || linkedResources.size() > 0 )
259         {
260             writer.startElement( "linkedResources" ); //$NON-NLS-1$
261             // preserve the symbolic links
262             if ( linkedResources.size() > 0 )
263             {
264                 for ( Iterator it = linkedResources.iterator(); it.hasNext(); )
265                 {
266                     ( (LinkedResource) it.next() ).print( writer );
267                 }
268             }
269 
270             if ( addLinks )
271             {
272 
273                 addFileLink( writer, config.getProjectBaseDir(), config.getEclipseProjectDirectory(),
274                              config.getProject().getFile() );
275 
276                 addSourceLinks( writer, config.getProjectBaseDir(), config.getEclipseProjectDirectory(),
277                                 config.getProject().getCompileSourceRoots() );
278                 addResourceLinks( writer, config.getProjectBaseDir(), config.getEclipseProjectDirectory(),
279                                   config.getProject().getBuild().getResources() );
280 
281                 addSourceLinks( writer, config.getProjectBaseDir(), config.getEclipseProjectDirectory(),
282                                 config.getProject().getTestCompileSourceRoots() );
283                 addResourceLinks( writer, config.getProjectBaseDir(), config.getEclipseProjectDirectory(),
284                                   config.getProject().getBuild().getTestResources() );
285 
286             }
287 
288             if ( config.isPde() )
289             {
290                 for ( int j = 0; j < dependencies.length; j++ )
291                 {
292                     IdeDependency dep = dependencies[j];
293 
294                     if ( dep.isAddedToClasspath() && !dep.isProvided() && !dep.isReferencedProject()
295                         && !dep.isTestDependency() && !dep.isOsgiBundle() )
296                     {
297                         String name = dep.getFile().getName();
298                         addLink( writer, name, IdeUtils.fixSeparator( IdeUtils.getCanonicalPath( dep.getFile() ) ),
299                                  LINK_TYPE_FILE );
300                     }
301                 }
302             }
303 
304             writer.endElement(); // linkedResources
305         }
306 
307         writer.endElement(); // projectDescription
308 
309         IOUtil.close( w );
310     }
311 
312     private void addFileLink( XMLWriter writer, File projectBaseDir, File basedir, File file )
313         throws MojoExecutionException
314     {
315         if ( file.isFile() )
316         {
317             String name = IdeUtils.toRelativeAndFixSeparator( projectBaseDir, file, true );
318             String location = IdeUtils.fixSeparator( IdeUtils.getCanonicalPath( file ) );
319 
320             addLink( writer, name, location, LINK_TYPE_FILE );
321         }
322         else
323         {
324             log.warn( Messages.getString( "EclipseProjectWriter.notafile", file ) ); //$NON-NLS-1$
325         }
326     }
327 
328     private void addSourceLinks( XMLWriter writer, File projectBaseDir, File basedir, List sourceRoots )
329         throws MojoExecutionException
330     {
331         for ( Iterator it = sourceRoots.iterator(); it.hasNext(); )
332         {
333             String sourceRootString = (String) it.next();
334             File sourceRoot = new File( sourceRootString );
335 
336             if ( sourceRoot.isDirectory() )
337             {
338                 String name = IdeUtils.toRelativeAndFixSeparator( projectBaseDir, sourceRoot, true );
339                 String location = IdeUtils.fixSeparator( IdeUtils.getCanonicalPath( sourceRoot ) );
340 
341                 addLink( writer, name, location, LINK_TYPE_DIRECTORY );
342             }
343         }
344     }
345 
346     private void addResourceLinks( XMLWriter writer, File projectBaseDir, File basedir, List sourceRoots )
347         throws MojoExecutionException
348     {
349         for ( Iterator it = sourceRoots.iterator(); it.hasNext(); )
350         {
351             String resourceDirString = ( (Resource) it.next() ).getDirectory();
352             File resourceDir = new File( resourceDirString );
353 
354             if ( resourceDir.isDirectory() )
355             {
356                 String name = IdeUtils.toRelativeAndFixSeparator( projectBaseDir, resourceDir, true );
357                 String location = IdeUtils.fixSeparator( IdeUtils.getCanonicalPath( resourceDir ) );
358 
359                 addLink( writer, name, location, LINK_TYPE_DIRECTORY );
360             }
361         }
362     }
363 
364     /**
365      * @param writer
366      * @param name
367      * @param location
368      */
369     private void addLink( XMLWriter writer, String name, String location, int type )
370     {
371         // Avoid duplicates entries of the link..
372         if ( !linkNames.contains( name ) )
373         {
374 
375             writer.startElement( "link" ); //$NON-NLS-1$
376 
377             writer.startElement( ELT_NAME );
378             writer.writeText( name );
379             writer.endElement(); // name
380 
381             writer.startElement( "type" ); //$NON-NLS-1$
382             writer.writeText( Integer.toString( type ) );
383             writer.endElement(); // type
384 
385             writer.startElement( "location" ); //$NON-NLS-1$
386 
387             writer.writeText( location );
388 
389             writer.endElement(); // location
390 
391             writer.endElement(); // link
392         }
393     }
394 
395     private void addComment( XMLWriter writer, String projectDescription )
396     {
397         String comment = "";
398 
399         if ( projectDescription != null )
400         {
401             comment = projectDescription.trim();
402 
403             if ( comment.length() > 0 )
404             {
405                 if ( !comment.endsWith( "." ) )
406                 {
407                     comment += ".";
408                 }
409                 comment += " ";
410             }
411         }
412 
413         //
414         // Project files that are generated with m-p-e cannot be supported by M2Eclipse
415         //
416         comment += "NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse.";
417 
418         writer.startElement( ELT_COMMENT );
419         writer.writeText( comment );
420         writer.endElement();
421     }
422 
423 }