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.Iterator;
30  import java.util.LinkedHashSet;
31  import java.util.List;
32  import java.util.Set;
33  
34  import org.apache.maven.model.Resource;
35  import org.apache.maven.plugin.MojoExecutionException;
36  import org.apache.maven.plugin.eclipse.BuildCommand;
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  import org.codehaus.plexus.util.xml.Xpp3Dom;
45  import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
46  import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
47  
48  /**
49   * Writes eclipse .project file.
50   * 
51   * @author <a href="mailto:trygvis@inamo.no">Trygve Laugst&oslash;l</a>
52   * @author <a href="mailto:kenney@neonics.com">Kenney Westerhof</a>
53   * @author <a href="mailto:fgiust@apache.org">Fabrizio Giustina</a>
54   * @version $Id: EclipseProjectWriter.java 616816 2008-01-30 17:23:08Z aheritier $
55   */
56  public class EclipseProjectWriter
57      extends AbstractEclipseWriter
58  {
59      private static final String ELT_NAME = "name"; //$NON-NLS-1$
60  
61      private static final String ELT_BUILD_COMMAND = "buildCommand"; //$NON-NLS-1$
62  
63      private static final String ELT_BUILD_SPEC = "buildSpec"; //$NON-NLS-1$
64  
65      private static final String ELT_NATURE = "nature"; //$NON-NLS-1$
66  
67      private static final String ELT_NATURES = "natures"; //$NON-NLS-1$
68  
69      private static final String FILE_DOT_PROJECT = ".project"; //$NON-NLS-1$
70  
71      /**
72       * Constant for links to files.
73       */
74      private static final int LINK_TYPE_FILE = 1;
75  
76      /**
77       * Constant for links to directories.
78       */
79      private static final int LINK_TYPE_DIRECTORY = 2;
80  
81      /**
82       * @see org.apache.maven.plugin.eclipse.writers.EclipseWriter#write()
83       */
84      public void write()
85          throws MojoExecutionException
86      {
87  
88          Set projectnatures = new LinkedHashSet();
89          Set buildCommands = new LinkedHashSet();
90  
91          File dotProject = new File( config.getEclipseProjectDirectory(), FILE_DOT_PROJECT );
92  
93          if ( dotProject.exists() )
94          {
95  
96              log.info( Messages.getString( "EclipsePlugin.keepexisting", dotProject.getAbsolutePath() ) ); //$NON-NLS-1$
97  
98              // parse existing file in order to keep manually-added entries
99              Reader reader = null;
100             try
101             {
102                 reader = new InputStreamReader( new FileInputStream( dotProject ), "UTF-8" );
103                 Xpp3Dom dom = Xpp3DomBuilder.build( reader );
104 
105                 Xpp3Dom naturesElement = dom.getChild( ELT_NATURES );
106                 if ( naturesElement != null )
107                 {
108                     Xpp3Dom[] existingNatures = naturesElement.getChildren( ELT_NATURE );
109                     for ( int j = 0; j < existingNatures.length; j++ )
110                     {
111                         // adds all the existing natures
112                         projectnatures.add( existingNatures[j].getValue() );
113                     }
114                 }
115 
116                 Xpp3Dom buildSpec = dom.getChild( ELT_BUILD_SPEC );
117                 if ( buildSpec != null )
118                 {
119                     Xpp3Dom[] existingBuildCommands = buildSpec.getChildren( ELT_BUILD_COMMAND );
120                     for ( int j = 0; j < existingBuildCommands.length; j++ )
121                     {
122                         Xpp3Dom buildCommandName = existingBuildCommands[j].getChild( ELT_NAME );
123                         if ( buildCommandName != null )
124                         {
125                             buildCommands.add( new BuildCommand( existingBuildCommands[j] ) );
126                         }
127                     }
128                 }
129             }
130             catch ( XmlPullParserException e )
131             {
132                 log.warn( Messages.getString( "EclipsePlugin.cantparseexisting", dotProject.getAbsolutePath() ) ); //$NON-NLS-1$
133             }
134             catch ( IOException e )
135             {
136                 log.warn( Messages.getString( "EclipsePlugin.cantparseexisting", dotProject.getAbsolutePath() ) ); //$NON-NLS-1$
137             }
138             finally
139             {
140                 IOUtil.close( reader );
141             }
142         }
143 
144         // adds new entries after the existing ones
145         for ( Iterator iter = config.getProjectnatures().iterator(); iter.hasNext(); )
146         {
147             projectnatures.add( iter.next() );
148         }
149 
150         for ( Iterator iter = config.getBuildCommands().iterator(); iter.hasNext(); )
151         {
152             buildCommands.add( (BuildCommand) iter.next() );
153         }
154 
155         Writer w;
156 
157         try
158         {
159             w = new OutputStreamWriter( new FileOutputStream( dotProject ), "UTF-8" );
160         }
161         catch ( IOException ex )
162         {
163             throw new MojoExecutionException( Messages.getString( "EclipsePlugin.erroropeningfile" ), ex ); //$NON-NLS-1$
164         }
165 
166         XMLWriter writer = new PrettyPrintXMLWriter( w );
167 
168         writer.startElement( "projectDescription" ); //$NON-NLS-1$
169 
170         writer.startElement( ELT_NAME );
171         writer.writeText( config.getEclipseProjectName() );
172         writer.endElement();
173 
174         // TODO: this entire element might be dropped if the comment is null.
175         // but as the maven1 eclipse plugin does it, it's better to be safe than sorry
176         // A eclipse developer might want to look at this.
177         writer.startElement( "comment" ); //$NON-NLS-1$
178 
179         if ( config.getProject().getDescription() != null )
180         {
181             writer.writeText( config.getProject().getDescription() );
182         }
183 
184         writer.endElement();
185 
186         writer.startElement( "projects" ); //$NON-NLS-1$
187 
188         // referenced projects should not be added for plugins
189         if ( !config.isPde() )
190         {
191             for ( int j = 0; j < config.getDepsOrdered().length; j++ )
192             {
193                 IdeDependency dep = config.getDepsOrdered()[j];
194                 if ( dep.isReferencedProject() )
195                 {
196                     writer.startElement( "project" ); //$NON-NLS-1$
197                     writer.writeText( dep.getEclipseProjectName() );
198                     writer.endElement();
199                 }
200             }
201         }
202 
203         writer.endElement(); // projects
204 
205         writer.startElement( ELT_BUILD_SPEC );
206 
207         for ( Iterator it = buildCommands.iterator(); it.hasNext(); )
208         {
209             ( (BuildCommand) it.next() ).print( writer );
210         }
211 
212         writer.endElement(); // buildSpec
213 
214         writer.startElement( ELT_NATURES );
215 
216         for ( Iterator it = projectnatures.iterator(); it.hasNext(); )
217         {
218             writer.startElement( ELT_NATURE );
219             writer.writeText( (String) it.next() );
220             writer.endElement(); // name
221         }
222 
223         writer.endElement(); // natures
224 
225         boolean addLinks = !config.getProjectBaseDir().equals( config.getEclipseProjectDirectory() );
226 
227         if ( addLinks || ( config.isPde() && config.getDepsOrdered().length > 0 ) )
228         {
229             writer.startElement( "linkedResources" ); //$NON-NLS-1$
230 
231             if ( addLinks )
232             {
233 
234                 addFileLink( writer, config.getProjectBaseDir(), config.getEclipseProjectDirectory(),
235                              config.getProject().getFile() );
236 
237                 addSourceLinks( writer, config.getProjectBaseDir(), config.getEclipseProjectDirectory(),
238                                 config.getProject().getCompileSourceRoots() );
239                 addResourceLinks( writer, config.getProjectBaseDir(), config.getEclipseProjectDirectory(),
240                                   config.getProject().getBuild().getResources() );
241 
242                 addSourceLinks( writer, config.getProjectBaseDir(), config.getEclipseProjectDirectory(),
243                                 config.getProject().getTestCompileSourceRoots() );
244                 addResourceLinks( writer, config.getProjectBaseDir(), config.getEclipseProjectDirectory(),
245                                   config.getProject().getBuild().getTestResources() );
246 
247             }
248 
249             if ( config.isPde() )
250             {
251                 for ( int j = 0; j < config.getDepsOrdered().length; j++ )
252                 {
253                     IdeDependency dep = config.getDepsOrdered()[j];
254 
255                     if ( dep.isAddedToClasspath() && !dep.isProvided() && !dep.isReferencedProject() &&
256                         !dep.isTestDependency() && !dep.isOsgiBundle() )
257                     {
258                         String name = dep.getFile().getName();
259                         addLink( writer, name, StringUtils.replace( IdeUtils.getCanonicalPath( dep.getFile() ), "\\",
260                                                                     "/" ), LINK_TYPE_FILE );
261                     }
262                 }
263             }
264 
265             writer.endElement(); // linkedResources
266         }
267 
268         writer.endElement(); // projectDescription
269 
270         IOUtil.close( w );
271     }
272 
273     private void addFileLink( XMLWriter writer, File projectBaseDir, File basedir, File file )
274         throws MojoExecutionException
275     {
276         if ( file.isFile() )
277         {
278             String name = IdeUtils.toRelativeAndFixSeparator( projectBaseDir, file, true );
279             String location = IdeUtils.getCanonicalPath( file ).replaceAll( "\\\\", "/" ); //$NON-NLS-1$ //$NON-NLS-2$
280 
281             addLink( writer, name, location, LINK_TYPE_FILE );
282         }
283         else
284         {
285             log.warn( Messages.getString( "EclipseProjectWriter.notafile", file ) ); //$NON-NLS-1$
286         }
287     }
288 
289     private void addSourceLinks( XMLWriter writer, File projectBaseDir, File basedir, List sourceRoots )
290         throws MojoExecutionException
291     {
292         for ( Iterator it = sourceRoots.iterator(); it.hasNext(); )
293         {
294             String sourceRootString = (String) it.next();
295             File sourceRoot = new File( sourceRootString );
296 
297             if ( sourceRoot.isDirectory() )
298             {
299                 String name = IdeUtils.toRelativeAndFixSeparator( projectBaseDir, sourceRoot, true );
300                 String location = IdeUtils.getCanonicalPath( sourceRoot ).replaceAll( "\\\\", "/" ); //$NON-NLS-1$ //$NON-NLS-2$
301 
302                 addLink( writer, name, location, LINK_TYPE_DIRECTORY );
303             }
304         }
305     }
306 
307     private void addResourceLinks( XMLWriter writer, File projectBaseDir, File basedir, List sourceRoots )
308         throws MojoExecutionException
309     {
310         for ( Iterator it = sourceRoots.iterator(); it.hasNext(); )
311         {
312             String resourceDirString = ( (Resource) it.next() ).getDirectory();
313             File resourceDir = new File( resourceDirString );
314 
315             if ( resourceDir.isDirectory() )
316             {
317                 String name = IdeUtils.toRelativeAndFixSeparator( projectBaseDir, resourceDir, true );
318                 String location = IdeUtils.getCanonicalPath( resourceDir ).replaceAll( "\\\\", "/" ); //$NON-NLS-1$ //$NON-NLS-2$
319 
320                 addLink( writer, name, location, LINK_TYPE_DIRECTORY );
321             }
322         }
323     }
324 
325     /**
326      * @param writer
327      * @param name
328      * @param location
329      */
330     private void addLink( XMLWriter writer, String name, String location, int type )
331     {
332         writer.startElement( "link" ); //$NON-NLS-1$
333 
334         writer.startElement( ELT_NAME );
335         writer.writeText( name );
336         writer.endElement(); // name
337 
338         writer.startElement( "type" ); //$NON-NLS-1$
339         writer.writeText( Integer.toString( type ) );
340         writer.endElement(); // type
341 
342         writer.startElement( "location" ); //$NON-NLS-1$
343 
344         writer.writeText( location );
345 
346         writer.endElement(); // location
347 
348         writer.endElement(); // link
349     }
350 }