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;
20  
21  import java.io.File;
22  import java.io.FileOutputStream;
23  import java.io.IOException;
24  import java.io.InputStream;
25  import java.io.OutputStream;
26  import java.util.ArrayList;
27  import java.util.Arrays;
28  import java.util.Iterator;
29  import java.util.LinkedHashSet;
30  import java.util.LinkedList;
31  import java.util.List;
32  import java.util.ListIterator;
33  import java.util.Map;
34  import java.util.Set;
35  
36  import org.apache.maven.artifact.Artifact;
37  import org.apache.maven.artifact.handler.ArtifactHandler;
38  import org.apache.maven.model.Build;
39  import org.apache.maven.model.Plugin;
40  import org.apache.maven.model.Resource;
41  import org.apache.maven.plugin.MojoExecutionException;
42  import org.apache.maven.plugin.eclipse.reader.ReadWorkspaceLocations;
43  import org.apache.maven.plugin.eclipse.writers.EclipseAjdtWriter;
44  import org.apache.maven.plugin.eclipse.writers.EclipseClasspathWriter;
45  import org.apache.maven.plugin.eclipse.writers.EclipseManifestWriter;
46  import org.apache.maven.plugin.eclipse.writers.EclipseOSGiManifestWriter;
47  import org.apache.maven.plugin.eclipse.writers.EclipseProjectWriter;
48  import org.apache.maven.plugin.eclipse.writers.EclipseSettingsWriter;
49  import org.apache.maven.plugin.eclipse.writers.EclipseWriterConfig;
50  import org.apache.maven.plugin.eclipse.writers.wtp.EclipseWtpApplicationXMLWriter;
51  import org.apache.maven.plugin.eclipse.writers.wtp.EclipseWtpComponent15Writer;
52  import org.apache.maven.plugin.eclipse.writers.wtp.EclipseWtpComponentWriter;
53  import org.apache.maven.plugin.eclipse.writers.wtp.EclipseWtpFacetsWriter;
54  import org.apache.maven.plugin.eclipse.writers.wtp.EclipseWtpmodulesWriter;
55  import org.apache.maven.plugin.ide.AbstractIdeSupportMojo;
56  import org.apache.maven.plugin.ide.IdeDependency;
57  import org.apache.maven.plugin.ide.IdeUtils;
58  import org.apache.maven.plugin.ide.JeeUtils;
59  import org.apache.maven.project.MavenProject;
60  import org.codehaus.plexus.resource.ResourceManager;
61  import org.codehaus.plexus.resource.loader.FileResourceLoader;
62  import org.codehaus.plexus.resource.loader.ResourceNotFoundException;
63  import org.codehaus.plexus.util.FileUtils;
64  import org.codehaus.plexus.util.IOUtil;
65  import org.codehaus.plexus.util.StringUtils;
66  import org.codehaus.plexus.util.xml.Xpp3Dom;
67  
68  /**
69   * Generates the following eclipse configuration files:
70   * <ul>
71   * <li><code>.project</code> and <code>.classpath</code> files</li>
72   * <li><code>.setting/org.eclipse.jdt.core.prefs</code> with project specific compiler settings</li>
73   * <li>various configuration files for WTP (Web Tools Project), if the parameter <code>wtpversion</code> is set to a
74   * valid version (WTP configuration is not generated by default)</li>
75   * </ul>
76   * If this goal is run on a multiproject root, dependencies between modules will be configured as direct project
77   * dependencies in Eclipse (unless <code>useProjectReferences</code> is set to <code>false</code>).
78   * 
79   * @author <a href="mailto:trygvis@inamo.no">Trygve Laugst&oslash;l</a>
80   * @author <a href="mailto:fgiust@apache.org">Fabrizio Giustina</a>
81   * @version $Id: EclipsePlugin.java 756392 2009-03-20 09:46:09Z baerrach $
82   * @goal eclipse
83   * @execute phase="generate-resources"
84   */
85  public class EclipsePlugin
86  extends AbstractIdeSupportMojo
87  {
88      private static final String WEAVE_DEPENDENCY = "weaveDependency";
89  
90      private static final String WEAVE_DEPENDENCIES = "weaveDependencies";
91  
92      private static final String ASPECT_LIBRARY = "aspectLibrary";
93  
94      private static final String ASPECT_LIBRARIES = "aspectLibraries";
95  
96      private static final String ASPECT_DIRECTORY = "aspectDirectory";
97  
98      private static final String TEST_ASPECT_DIRECTORY = "testAspectDirectory";
99  
100     private static final String ASPECTJ_MAVEN_PLUGIN = "aspectj-maven-plugin";
101 
102     private static final String ORG_CODEHAUS_MOJO = "org.codehaus.mojo";
103 
104     private static final String DEFAULT_TEST_ASPECT_DIRECTORY = "src/test/aspect";
105 
106     private static final String DEFAULT_ASPECT_DIRECTORY = "src/main/aspect";
107 
108     private static final String NATURE_WST_FACET_CORE_NATURE = "org.eclipse.wst.common.project.facet.core.nature"; //$NON-NLS-1$
109 
110     private static final String BUILDER_WST_COMPONENT_STRUCTURAL_DEPENDENCY_RESOLVER =
111         "org.eclipse.wst.common.modulecore.ComponentStructuralBuilderDependencyResolver"; //$NON-NLS-1$
112 
113     protected static final String BUILDER_WST_VALIDATION = "org.eclipse.wst.validation.validationbuilder"; //$NON-NLS-1$
114 
115     private static final String BUILDER_JDT_CORE_JAVA = "org.eclipse.jdt.core.javabuilder"; //$NON-NLS-1$
116 
117     private static final String BUILDER_WST_COMPONENT_STRUCTURAL =
118         "org.eclipse.wst.common.modulecore.ComponentStructuralBuilder"; //$NON-NLS-1$
119 
120     private static final String BUILDER_WST_FACET = "org.eclipse.wst.common.project.facet.core.builder"; //$NON-NLS-1$
121 
122     private static final String BUILDER_PDE_MANIFEST = "org.eclipse.pde.ManifestBuilder"; //$NON-NLS-1$
123 
124     private static final String BUILDER_PDE_SCHEMA = "org.eclipse.pde.SchemaBuilder"; //$NON-NLS-1$
125 
126     private static final String BUILDER_AJDT_CORE_JAVA = "org.eclipse.ajdt.core.ajbuilder"; //$NON-NLS-1$
127 
128     private static final String NATURE_WST_MODULE_CORE_NATURE = "org.eclipse.wst.common.modulecore.ModuleCoreNature"; //$NON-NLS-1$
129 
130     private static final String NATURE_JDT_CORE_JAVA = "org.eclipse.jdt.core.javanature"; //$NON-NLS-1$
131 
132     private static final String NATURE_JEM_WORKBENCH_JAVA_EMF = "org.eclipse.jem.workbench.JavaEMFNature"; //$NON-NLS-1$
133 
134     private static final String NATURE_PDE_PLUGIN = "org.eclipse.pde.PluginNature"; //$NON-NLS-1$
135 
136     private static final String NATURE_AJDT_CORE_JAVA = "org.eclipse.ajdt.ui.ajnature"; //$NON-NLS-1$
137 
138     protected static final String COMMON_PATH_JDT_LAUNCHING_JRE_CONTAINER = "org.eclipse.jdt.launching.JRE_CONTAINER"; //$NON-NLS-1$
139 
140     protected static final String ASPECTJ_RT_CONTAINER = "org.eclipse.ajdt.core.ASPECTJRT_CONTAINER"; //$NON-NLS-1$
141 
142     protected static final String REQUIRED_PLUGINS_CONTAINER = "org.eclipse.pde.core.requiredPlugins"; //$NON-NLS-1$
143 
144     // warning, order is important for binary search
145     public static final String[] WTP_SUPPORTED_VERSIONS = new String[] { "1.0", "1.5", "2.0", "R7", "none" }; //$NON-NLS-1$ //$NON-NLS-2$  //$NON-NLS-3$
146 
147     /**
148      * Constant for 'artifactId' element in POM.xml.
149      */
150     private static final String POM_ELT_ARTIFACT_ID = "artifactId"; //$NON-NLS-1$
151 
152     /**
153      * Constant for 'groupId' element in POM.xml.
154      */
155     private static final String POM_ELT_GROUP_ID = "groupId"; //$NON-NLS-1$
156 
157     /**
158      * List of eclipse project natures. By default the <code>org.eclipse.jdt.core.javanature</code> nature plus the
159      * needed WTP natures are added. Natures added using this property <strong>replace</strong> the default list.
160      * 
161      * <pre>
162      * &lt;projectnatures&gt;
163      *    &lt;projectnature&gt;org.eclipse.jdt.core.javanature&lt;/projectnature&gt;
164      *    &lt;projectnature&gt;org.eclipse.wst.common.modulecore.ModuleCoreNature&lt;/projectnature&gt;
165      * &lt;/projectnatures&gt;
166      * </pre>
167      * 
168      * @parameter
169      */
170     private List projectnatures;
171 
172     /**
173      * List of artifact to exclude from eclipse classpath, beeing provided by some eclipse classPathContainer
174      * [MECLIPSE-79]
175      * 
176      * @since 2.5
177      * @parameter
178      */
179     private List excludes;
180 
181     /**
182      * List of eclipse project natures to be added to the default ones.
183      * 
184      * <pre>
185      * &lt;additionalProjectnatures&gt;
186      *    &lt;projectnature&gt;org.springframework.ide.eclipse.core.springnature&lt;/projectnature&gt;
187      * &lt;/additionalProjectnatures&gt;
188      * </pre>
189      * 
190      * @parameter
191      */
192     private List additionalProjectnatures;
193 
194     /**
195      * List of eclipse project facets to be added to the default ones.
196      * 
197      * <pre>
198      * &lt;additionalProjectFacets&gt;
199      *    &lt;jst.jsf&gt;1.1&lt;jst.jsf/&gt;
200      * &lt;/additionalProjectFacets&gt;
201      * </pre>
202      * 
203      * @parameter
204      */
205     private Map additionalProjectFacets;
206 
207     /**
208      * List of eclipse build commands. By default the <code>org.eclipse.jdt.core.javabuilder</code> builder plus the
209      * needed WTP builders are added. If you specify any configuration for this parameter, only those buildcommands
210      * specified will be used; the defaults won't be added. Use the <code>additionalBuildCommands</code> parameter for
211      * that. Configuration example: Old style:
212      * 
213      * <pre>
214      * &lt;buildcommands&gt;
215      *    &lt;buildcommand&gt;org.eclipse.wst.common.modulecore.ComponentStructuralBuilder&lt;/buildcommand&gt;
216      *    &lt;buildcommand&gt;org.eclipse.jdt.core.javabuilder&lt;/buildcommand&gt;
217      *    &lt;buildcommand&gt;org.eclipse.wst.common.modulecore.ComponentStructuralBuilderDependencyResolver&lt;/buildcommand&gt;
218      * &lt;/buildcommands&gt;
219      * </pre>
220      * 
221      * For new style, see <code>additionalBuildCommands</code>.
222      * 
223      * @parameter
224      */
225     private List buildcommands;
226 
227     /**
228      * List of eclipse build commands to be added to the default ones. Old style:
229      * 
230      * <pre>
231      * &lt;additionalBuildcommands&gt;
232      *    &lt;buildcommand&gt;org.springframework.ide.eclipse.core.springbuilder&lt;/buildcommand&gt;
233      * &lt;/additionalBuildcommands&gt;
234      * </pre>
235      * 
236      * New style:
237      * 
238      * <pre>
239      * &lt;additionalBuildcommands&gt;
240      *    &lt;buildCommand&gt;
241      *      &lt;name&gt;org.ui.externaltools.ExternalToolBuilder&lt;/name&gt;
242      *      &lt;triggers&gt;auto,full,incremental,&lt;/triggers&gt;
243      *      &lt;arguments&gt;
244      *        &lt;LaunchConfigHandle&gt;&amp;lt;project&amp;gt;./externalToolBuilders/MavenBuilder.launch&lt;/LaunchConfighandle&gt;
245      *      &lt;/arguments&gt;
246      *    &lt;/buildCommand&gt;
247      * &lt;/additionalBuildcommands&gt;
248      * </pre>
249      * 
250      * Note the difference between <code>build<strong>c</strong>ommand</code> and
251      * <code>build<strong>C</strong>ommand</code>. You can mix and match old and new-style configuration entries.
252      * 
253      * @parameter
254      */
255     private List additionalBuildcommands;
256 
257     /**
258      * List of container classpath entries. By default the <code>org.eclipse.jdt.launching.JRE_CONTAINER</code>
259      * classpath container is added. Configuration example:
260      * 
261      * <pre>
262      * &lt;classpathContainers&gt;
263      *    &lt;classpathContainer&gt;org.eclipse.jdt.launching.JRE_CONTAINER&lt;/classpathContainer&gt;
264      *    &lt;classpathContainer&gt;org.eclipse.jst.server.core.container/org.eclipse.jst.server.tomcat.runtimeTarget/Apache Tomcat v5.5&lt;/classpathContainer&gt;
265      *    &lt;classpathContainer&gt;org.eclipse.jst.j2ee.internal.web.container/artifact&lt;/classpathContainer&gt;
266      * &lt;/classpathContainers&gt;
267      * </pre>
268      * 
269      * @parameter
270      */
271     private List classpathContainers;
272 
273     /**
274      * Enables/disables the downloading of source attachments. Defaults to false. DEPRECATED - use downloadSources
275      * 
276      * @parameter expression="${eclipse.downloadSources}"
277      * @deprecated use downloadSources
278      */
279     private boolean eclipseDownloadSources;
280 
281     /**
282      * Eclipse workspace directory.
283      * 
284      * @parameter expression="${eclipse.projectDir}" alias="outputDir"
285      */
286     private File eclipseProjectDir;
287 
288     /**
289      * When set to false, the plugin will not create sub-projects and instead reference those sub-projects using the
290      * installed package in the local repository
291      * 
292      * @parameter expression="${eclipse.useProjectReferences}" default-value="true"
293      * @required
294      */
295     private boolean useProjectReferences;
296 
297     /**
298      * The default output directory
299      * 
300      * @parameter expression="${outputDirectory}" alias="outputDirectory"
301      *            default-value="${project.build.outputDirectory}"
302      * @required
303      */
304     private File buildOutputDirectory;
305 
306     /**
307      * The version of WTP for which configuration files will be generated. The default value is "none" (don't generate
308      * WTP configuration), supported versions are "R7", "1.0", and "1.5"
309      * 
310      * @parameter expression="${wtpversion}" default-value="none"
311      */
312     private String wtpversion;
313 
314     /**
315      * JEE context name of the WTP module. ( ex. WEB context name ).
316      * 
317      * @parameter expression="${wtpContextName}"
318      */
319     private String wtpContextName;
320 
321     /**
322      * Is it an PDE project? If yes, the plugin adds the necessary natures and build commands to the .project file.
323      * Additionally it copies all libraries to a project local directory and references them instead of referencing the
324      * files in the local Maven repository. It also ensured that the "Bundle-Classpath" in META-INF/MANIFEST.MF is
325      * synchronized.
326      * 
327      * @parameter expression="${eclipse.pde}" default-value="false"
328      */
329     private boolean pde;
330 
331     /**
332      * Is it an AJDT project? If yes, the plugin adds the necessary natures and build commands to the .project file.
333      */
334     private boolean ajdt;
335 
336     /**
337      * The relative path of the manifest file
338      * 
339      * @parameter expression="${eclipse.manifest}" default-value="${basedir}/META-INF/MANIFEST.MF"
340      */
341     private File manifest;
342 
343     /**
344      * Allow to configure additional generic configuration files for eclipse that will be written out to disk when
345      * running eclipse:eclipse. FOr each file you can specify the name and the text content.
346      * 
347      * <pre>
348      * &lt;plugin&gt;
349      *  &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
350      *  &lt;artifactId&gt;maven-eclipse-plugin&lt;/artifactId&gt;
351      *  &lt;configuration&gt;
352      *   &lt;additionalConfig&gt;
353      *    &lt;file&gt;
354      *      &lt;name&gt;.checkstyle&lt;/name&gt;
355      *      &lt;content&gt;
356      *        &lt;![CDATA[&lt;fileset-config file-format-version=&quot;1.2.0&quot; simple-config=&quot;true&quot;&gt;
357      *          &lt;fileset name=&quot;all&quot; enabled=&quot;true&quot; check-config-name=&quot;acme corporate style&quot; local=&quot;false&quot;&gt;
358      *              &lt;file-match-pattern match-pattern=&quot;.&quot; include-pattern=&quot;true&quot;/&gt;
359      *          &lt;/fileset&gt;
360      *          &lt;filter name=&quot;NonSrcDirs&quot; enabled=&quot;true&quot;/&gt;
361      *        &lt;/fileset-config&gt;]]&gt;
362      *      &lt;/content&gt;
363      *    &lt;/file&gt;
364      *   &lt;/additionalConfig&gt;
365      *  &lt;/configuration&gt;
366      * &lt;/plugin&gt;
367      * </pre>
368      * 
369      * Instead of the content you can also define (from version 2.5) an url to download the file :
370      * 
371      * <pre>
372      * &lt;plugin&gt;
373      *  &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
374      *  &lt;artifactId&gt;maven-eclipse-plugin&lt;/artifactId&gt;
375      *  &lt;configuration&gt;
376      *   &lt;additionalConfig&gt;
377      *    &lt;file&gt;
378      *      &lt;name&gt;.checkstyle&lt;/name&gt;
379      *      &lt;url&gt;http://some.place.org/path/to/file&lt;/url&gt;
380      *    &lt;/file&gt;
381      *   &lt;/additionalConfig&gt;
382      *  &lt;/configuration&gt;
383      * </pre>
384      * 
385      * or a location :
386      * 
387      * <pre>
388      * &lt;plugin&gt;
389      *  &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
390      *  &lt;artifactId&gt;maven-eclipse-plugin&lt;/artifactId&gt;
391      *  &lt;configuration&gt;
392      *   &lt;additionalConfig&gt;
393      *    &lt;file&gt;
394      *     &lt;name&gt;.checkstyle&lt;/name&gt;
395      *     &lt;location&gt;/checkstyle-config.xml&lt;/location&gt;
396      *    &lt;/file&gt;
397      *   &lt;/additionalConfig&gt;
398      *  &lt;/configuration&gt;
399      *  &lt;dependencies&gt;
400      *   &lt;!-- The file defined in the location is stored in this dependency --&gt;
401      *   &lt;dependency&gt;
402      *    &lt;groupId&gt;eclipsetest&lt;/groupId&gt;
403      *    &lt;artifactId&gt;checkstyle-config&lt;/artifactId&gt;
404      *    &lt;version&gt;1.0&lt;/version&gt;
405      *   &lt;/dependency&gt;
406      *  &lt;/dependencies&gt;
407      * &lt;/plugin&gt;
408      * </pre>
409      * 
410      * @parameter
411      */
412     private EclipseConfigFile[] additionalConfig;
413 
414     /**
415      * If set to <code>true</code>, the version number of the artifact is appended to the name of the generated Eclipse
416      * project. See projectNameTemplate for other options.
417      * 
418      * @parameter expression="${eclipse.addVersionToProjectName}" default-value="false"
419      */
420     private boolean addVersionToProjectName;
421 
422     /**
423      * If set to <code>true</code>, the groupId of the artifact is appended to the name of the generated Eclipse
424      * project. See projectNameTemplate for other options.
425      * 
426      * @parameter expression="${eclipse.addGroupIdToProjectName}" default-value="false"
427      */
428     private boolean addGroupIdToProjectName;
429 
430     /**
431      * Allows configuring the name of the eclipse projects. This property if set wins over addVersionToProjectName and
432      * addGroupIdToProjectName You can use <code>[groupId]</code>, <code>[artifactId]</code> and <code>[version]</code>
433      * variables. eg. <code>[groupId].[artifactId]-[version]</code>
434      * 
435      * @parameter expression="${eclipse.projectNameTemplate}"
436      */
437     private String projectNameTemplate;
438 
439     /**
440      * Parsed wtp version.
441      */
442     private float wtpVersionFloat;
443 
444     /**
445      * Not a plugin parameter. Is this a java project?
446      */
447     private boolean isJavaProject;
448 
449     /**
450      * Must the manifest files be written for java projects so that that the jee classpath for wtp is correct.
451      * 
452      * @parameter expression="${eclipse.wtpmanifest}" default-value="false"
453      */
454     private boolean wtpmanifest;
455 
456     /**
457      * Must the application files be written for ear projects in a separate directory.
458      * 
459      * @parameter expression="${eclipse.wtpapplicationxml}" default-value="false"
460      */
461     private boolean wtpapplicationxml;
462 
463     /**
464      * What WTP defined server to use for deployment informations.
465      * 
466      * @parameter expression="${eclipse.wtpdefaultserver}"
467      */
468     private String wtpdefaultserver;
469 
470     private WorkspaceConfiguration workspaceConfiguration;
471 
472     /**
473      * ResourceManager for getting additonalConfig files from resources
474      * 
475      * @component
476      * @required
477      * @readonly
478      */
479     private ResourceManager locator;
480 
481     /**
482      * This eclipse workspace is read and all artifacts detected there will be connected as eclipse projects and will
483      * not be linked to the jars in the local repository. Requirement is that it was created with the similar wtp
484      * settings as the reactor projects, but the project name template my differ. The pom's in the workspace projects
485      * may not contain variables in the artefactId, groupId and version tags.
486      * 
487      * If workspace is not defined, then an attempt to locate it by checking up the directory hierarchy will be made.
488      * 
489      * @since 2.5
490      * @parameter expression="${eclipse.workspace}"
491      */
492     protected File workspace;
493 
494     /**
495      * Limit the use of project references to the current workspace. No project references will be created to projects
496      * in the reactor when they are not available in the workspace.
497      * 
498      * @parameter expression="${eclipse.limitProjectReferencesToWorkspace}" default-value="false"
499      */
500     protected boolean limitProjectReferencesToWorkspace;
501 
502     /**
503      * The version of AJDT for which configuration files will be generated. The default value is "1.5", supported
504      * versions are "none", "1.4", and "1.5".
505      * 
506      * @parameter expression="${eclipse.ajdtVersion}" default-value="1.5"
507      */
508     private String ajdtVersion;
509 
510     protected final boolean isJavaProject()
511     {
512         return isJavaProject;
513     }
514 
515     protected final boolean isPdeProject()
516     {
517         return pde;
518     }
519 
520     /**
521      * Getter for <code>buildcommands</code>.
522      * 
523      * @return Returns the buildcommands.
524      */
525     public final List getBuildcommands()
526     {
527         return buildcommands;
528     }
529 
530     /**
531      * Setter for <code>buildcommands</code>.
532      * 
533      * @param buildcommands The buildcommands to set.
534      */
535     public final void setBuildcommands( List buildcommands )
536     {
537         this.buildcommands = buildcommands;
538     }
539 
540     /**
541      * Getter for <code>buildOutputDirectory</code>.
542      * 
543      * @return Returns the buildOutputDirectory.
544      */
545     public final File getBuildOutputDirectory()
546     {
547         return buildOutputDirectory;
548     }
549 
550     /**
551      * Setter for <code>buildOutputDirectory</code>.
552      * 
553      * @param buildOutputDirectory The buildOutputDirectory to set.
554      */
555     public final void setBuildOutputDirectory( File buildOutputDirectory )
556     {
557         this.buildOutputDirectory = buildOutputDirectory;
558     }
559 
560     /**
561      * Getter for <code>classpathContainers</code>.
562      * 
563      * @return Returns the classpathContainers.
564      */
565     public final List getClasspathContainers()
566     {
567         return classpathContainers;
568     }
569 
570     /**
571      * Setter for <code>classpathContainers</code>.
572      * 
573      * @param classpathContainers The classpathContainers to set.
574      */
575     public final void setClasspathContainers( List classpathContainers )
576     {
577         this.classpathContainers = classpathContainers;
578     }
579 
580     /**
581      * Getter for <code>eclipseProjectDir</code>.
582      * 
583      * @return Returns the eclipseProjectDir.
584      */
585     public final File getEclipseProjectDir()
586     {
587         return eclipseProjectDir;
588     }
589 
590     /**
591      * Setter for <code>eclipseProjectDir</code>.
592      * 
593      * @param eclipseProjectDir The eclipseProjectDir to set.
594      */
595     public final void setEclipseProjectDir( File eclipseProjectDir )
596     {
597         this.eclipseProjectDir = eclipseProjectDir;
598     }
599 
600     /**
601      * Getter for <code>projectnatures</code>.
602      * 
603      * @return Returns the projectnatures.
604      */
605     public final List getProjectnatures()
606     {
607         return projectnatures;
608     }
609 
610     /**
611      * Setter for <code>projectnatures</code>.
612      * 
613      * @param projectnatures The projectnatures to set.
614      */
615     public final void setProjectnatures( List projectnatures )
616     {
617         this.projectnatures = projectnatures;
618     }
619 
620     /**
621      * Getter for <code>useProjectReferences</code>.
622      * 
623      * @return Returns the useProjectReferences.
624      */
625     public final boolean getUseProjectReferences()
626     {
627         return useProjectReferences;
628     }
629 
630     /**
631      * Setter for <code>useProjectReferences</code>.
632      * 
633      * @param useProjectReferences The useProjectReferences to set.
634      */
635     public final void setUseProjectReferences( boolean useProjectReferences )
636     {
637         this.useProjectReferences = useProjectReferences;
638     }
639 
640     /**
641      * Getter for <code>wtpversion</code>.
642      * 
643      * @return Returns the wtpversion.
644      */
645     public final String getWtpversion()
646     {
647         return wtpversion;
648     }
649 
650     /**
651      * Setter for <code>wtpversion</code>.
652      * 
653      * @param wtpversion The wtpversion to set.
654      */
655     public final void setWtpversion( String wtpversion )
656     {
657         this.wtpversion = wtpversion;
658     }
659 
660     /**
661      * Getter for <code>additionalBuildcommands</code>.
662      * 
663      * @return Returns the additionalBuildcommands.
664      */
665     public final List getAdditionalBuildcommands()
666     {
667         return additionalBuildcommands;
668     }
669 
670     /**
671      * Setter for <code>additionalBuildcommands</code>.
672      * 
673      * @param additionalBuildcommands The additionalBuildcommands to set.
674      */
675     public final void setAdditionalBuildcommands( List additionalBuildcommands )
676     {
677         this.additionalBuildcommands = additionalBuildcommands;
678     }
679 
680     /**
681      * Getter for <code>additionalProjectnatures</code>.
682      * 
683      * @return Returns the additionalProjectnatures.
684      */
685     public final List getAdditionalProjectnatures()
686     {
687         return additionalProjectnatures;
688     }
689 
690     /**
691      * Setter for <code>additionalProjectnatures</code>.
692      * 
693      * @param additionalProjectnatures The additionalProjectnatures to set.
694      */
695     public final void setAdditionalProjectnatures( List additionalProjectnatures )
696     {
697         this.additionalProjectnatures = additionalProjectnatures;
698     }
699 
700     /**
701      * Getter for <code>addVersionToProjectName</code>.
702      */
703     public final boolean isAddVersionToProjectName()
704     {
705         return addVersionToProjectName;
706     }
707 
708     /**
709      * Setter for <code>addVersionToProjectName</code>.
710      */
711     public final void setAddVersionToProjectName( boolean addVersionToProjectName )
712     {
713         this.addVersionToProjectName = addVersionToProjectName;
714     }
715 
716     /**
717      * Getter for <code>addGroupIdToProjectName</code>.
718      */
719     public final boolean isAddGroupIdToProjectName()
720     {
721         return addGroupIdToProjectName;
722     }
723 
724     /**
725      * Setter for <code>addGroupIdToProjectName</code>.
726      */
727     public final void setAddGroupIdToProjectName( boolean addGroupIdToProjectName )
728     {
729         this.addGroupIdToProjectName = addGroupIdToProjectName;
730     }
731 
732     /**
733      * Getter for <code>projectNameTemplate</code>
734      * 
735      * @return projectNameTemplate
736      */
737     public final String getProjectNameTemplate()
738     {
739         return projectNameTemplate;
740     }
741 
742     /**
743      * Setter for <code>projectNameTemplate</code>.
744      * 
745      * @param projectNameTemplate projectNameTemplate
746      */
747     public final void setProjectNameTemplate( String projectNameTemplate )
748     {
749         this.projectNameTemplate = projectNameTemplate;
750     }
751 
752     /**
753      * @see org.apache.maven.plugin.Mojo#execute()
754      */
755     public final boolean setup()
756         throws MojoExecutionException
757     {
758         boolean ready = true;
759 
760         checkDeprecations();
761         setProjectNameTemplate( IdeUtils.calculateProjectNameTemplate( getProjectNameTemplate(), isAddVersionToProjectName(),
762                                                               isAddGroupIdToProjectName(), getLog() ) );
763         ajdt = enableAjdt( executedProject ) && !ajdtVersion.equals( "none" );
764         ready = validate();
765 
766         // TODO: Why are we using project in some places, and executedProject in others??
767         ArtifactHandler artifactHandler = project.getArtifact().getArtifactHandler();
768 
769         // ear projects don't contain java sources
770         // pde projects are always java projects
771         isJavaProject =
772             pde
773                 || ( Constants.LANGUAGE_JAVA.equals( artifactHandler.getLanguage() ) && !Constants.PROJECT_PACKAGING_EAR.equals( packaging ) );
774 
775         setupExtras();
776 
777         parseConfigurationOptions();
778 
779         // defaults
780         if ( projectnatures == null )
781         {
782             fillDefaultNatures( packaging );
783         }
784 
785         if ( additionalProjectnatures != null )
786         {
787             projectnatures.addAll( additionalProjectnatures );
788         }
789 
790         if ( buildcommands == null )
791         {
792             fillDefaultBuilders( packaging );
793         }
794         else
795         {
796             convertBuildCommandList( buildcommands );
797         }
798 
799         if ( additionalBuildcommands != null )
800         {
801             convertBuildCommandList( additionalBuildcommands );
802             buildcommands.addAll( additionalBuildcommands );
803         }
804 
805         if ( classpathContainers == null )
806         {
807             fillDefaultClasspathContainers( packaging );
808         }
809         else
810         {
811             verifyClasspathContainerListIsComplete();
812         }
813         locator.addSearchPath( FileResourceLoader.ID, project.getFile().getParentFile().getAbsolutePath() );
814         locator.setOutputDirectory( new File( project.getBuild().getDirectory() ) );
815 
816         // ready to start
817         return ready;
818     }
819 
820     /**
821      * Convert any Strings in the <code>commands</code> List to <code>BuildCommand</code>s. The conversion happens
822      * in situ.
823      * 
824      * @param commands a list of commands to convert into <code>BuildCommand</code>
825      */
826     protected final void convertBuildCommandList( List commands )
827     {
828         if ( commands != null )
829         {
830             for ( ListIterator i = commands.listIterator(); i.hasNext(); )
831             {
832                 Object command = i.next();
833 
834                 if ( command instanceof String )
835                 {
836                     command = new BuildCommand( (String) command );
837                     i.set( command );
838                 }
839             }
840         }
841     }
842 
843     private void parseConfigurationOptions()
844     {
845         if ( "R7".equalsIgnoreCase( wtpversion ) ) //$NON-NLS-1$
846         {
847             wtpVersionFloat = 0.7f;
848         }
849         else if ( "1.0".equalsIgnoreCase( wtpversion ) ) //$NON-NLS-1$
850         {
851             wtpVersionFloat = 1.0f;
852         }
853         else if ( "1.5".equalsIgnoreCase( wtpversion ) ) //$NON-NLS-1$
854         {
855             wtpVersionFloat = 1.5f;
856         }
857         else if ( "2.0".equalsIgnoreCase( wtpversion ) ) //$NON-NLS-1$
858         {
859             wtpVersionFloat = 2.0f;
860         }
861         if ( !"none".equalsIgnoreCase( wtpversion ) )
862         {
863             getLog().info( Messages.getString( "EclipsePlugin.wtpversion", wtpversion ) );
864         }
865     }
866 
867     /**
868      * Extension point for subclasses.
869      * <p>
870      * Called during <code>setup</code>.
871      * 
872      * @throws MojoExecutionException mojo failures.
873      */
874     protected void setupExtras()
875         throws MojoExecutionException
876     {
877         // extension point.
878     }
879 
880     private void verifyClasspathContainerListIsComplete()
881     {
882         boolean containsJREContainer = false;
883         // Check if classpathContainer contains a JRE (default, alternate or
884         // Execution Environment)
885         for ( Iterator iter = classpathContainers.iterator(); iter.hasNext(); )
886         {
887             Object classPathContainer = iter.next();
888             if ( classPathContainer != null
889                 && classPathContainer.toString().startsWith( COMMON_PATH_JDT_LAUNCHING_JRE_CONTAINER ) )
890             {
891                 containsJREContainer = true;
892                 break;
893             }
894         }
895         if ( !containsJREContainer )
896         {
897             getLog().warn( Messages.getString( "EclipsePlugin.missingjrecontainer" ) ); //$NON-NLS-1$
898             classpathContainers.add( 0, COMMON_PATH_JDT_LAUNCHING_JRE_CONTAINER );
899         }
900     }
901 
902     private boolean validate()
903         throws MojoExecutionException
904     {
905         // validate sanity of the current m2 project
906         if ( Arrays.binarySearch( WTP_SUPPORTED_VERSIONS, wtpversion ) < 0 )
907         {
908             throw new MojoExecutionException(
909                                               Messages.getString( "EclipsePlugin.unsupportedwtp", new Object[] { //$NON-NLS-1$
910                                                                   wtpversion,
911                                                                       StringUtils.join( WTP_SUPPORTED_VERSIONS, " " ) } ) ); //$NON-NLS-1$
912         }
913 
914         assertNotEmpty( executedProject.getGroupId(), POM_ELT_GROUP_ID );
915         assertNotEmpty( executedProject.getArtifactId(), POM_ELT_ARTIFACT_ID );
916 
917         if ( executedProject.getFile() == null || !executedProject.getFile().exists() )
918         {
919             throw new MojoExecutionException( Messages.getString( "EclipsePlugin.missingpom" ) ); //$NON-NLS-1$
920         }
921 
922         if ( "pom".equals( packaging ) && eclipseProjectDir == null ) //$NON-NLS-1$
923         {
924             getLog().info( Messages.getString( "EclipsePlugin.pompackaging" ) ); //$NON-NLS-1$
925             return false;
926         }
927 
928         if ( "eclipse-plugin".equals( packaging ) )
929         {
930             pde = true;
931         }
932 
933         if ( eclipseProjectDir == null )
934         {
935             eclipseProjectDir = executedProject.getFile().getParentFile();
936         }
937 
938         if ( !eclipseProjectDir.exists() && !eclipseProjectDir.mkdirs() )
939         {
940             throw new MojoExecutionException( Messages.getString( "EclipsePlugin.cantcreatedir", eclipseProjectDir ) ); //$NON-NLS-1$
941         }
942 
943         if ( !eclipseProjectDir.equals( executedProject.getFile().getParentFile() ) )
944         {
945             if ( !eclipseProjectDir.isDirectory() )
946             {
947                 throw new MojoExecutionException( Messages.getString( "EclipsePlugin.notadir", eclipseProjectDir ) ); //$NON-NLS-1$
948             }
949             eclipseProjectDir = new File( eclipseProjectDir, executedProject.getArtifactId() );
950             if ( !eclipseProjectDir.isDirectory() && !eclipseProjectDir.mkdirs() )
951             {
952                 throw new MojoExecutionException( Messages.getString( "EclipsePlugin.cantcreatedir", eclipseProjectDir ) ); //$NON-NLS-1$
953             }
954         }
955 
956         validateExtras();
957 
958         return true;
959     }
960 
961     /**
962      * Extension point for subclasses.
963      * <p>
964      * Called during <code>setup</code> and used to validate that the configuration is sane.
965      * 
966      * @throws MojoExecutionException mojo failures.
967      */
968     protected void validateExtras() throws MojoExecutionException
969     {
970         // provided for extension.
971     }
972 
973     private void checkDeprecations()
974     {
975         if ( eclipseDownloadSources )
976         {
977             // deprecated warning
978             getLog().warn( Messages.getString( "EclipsePlugin.deprecatedpar", new Object[] { //$NON-NLS-1$
979                                                "eclipse.downloadSources", //$NON-NLS-1$
980                                                    "downloadSources" } ) ); //$NON-NLS-1$
981             downloadSources = true;
982         }
983 
984         checkDeprecationsExtras();
985     }
986 
987     /**
988      * Extension point for subclasses.
989      * <p>
990      * Check for any extra deprecations and log warnings. Called during <code>setup</code>
991      */
992     protected void checkDeprecationsExtras()
993     {
994         // provided for extension.
995     }
996 
997     public final void writeConfiguration( IdeDependency[] deps )
998         throws MojoExecutionException
999     {
1000         EclipseWriterConfig config = createEclipseWriterConfig( deps );
1001 
1002         if ( wtpmanifest && isJavaProject() )
1003         {
1004             EclipseManifestWriter.addManifestResource( getLog(), config );
1005         }
1006         // NOTE: This could change the config!
1007         writeConfigurationExtras( config );
1008 
1009         if ( wtpVersionFloat == 0.7f )
1010         {
1011             new EclipseWtpmodulesWriter().init( getLog(), config ).write();
1012         }
1013 
1014         if ( wtpVersionFloat >= 1.0f )
1015         {
1016             new EclipseWtpFacetsWriter().init( getLog(), config ).write();
1017         }
1018         if ( wtpVersionFloat == 1.0f )
1019         {
1020             new EclipseWtpComponentWriter().init( getLog(), config ).write();
1021         }
1022         if ( wtpVersionFloat >= 1.5 )
1023         {
1024             new EclipseWtpComponent15Writer().init( getLog(), config ).write();
1025         }
1026 
1027         new EclipseSettingsWriter().init( getLog(), config ).write();
1028 
1029         if ( isJavaProject )
1030         {
1031             new EclipseClasspathWriter().init( getLog(), config ).write();
1032             if ( ajdt && ajdtVersion.equals( "1.4" ) )
1033             {
1034                 new EclipseAjdtWriter().init( getLog(), config ).write();
1035             }
1036         }
1037 
1038         if ( wtpapplicationxml )
1039         {
1040             new EclipseWtpApplicationXMLWriter().init( getLog(), config ).write();
1041         }
1042 
1043         if ( pde )
1044         {
1045             this.getLog().info( "The Maven Eclipse plugin runs in 'pde'-mode." );
1046             new EclipseOSGiManifestWriter().init( getLog(), config ).write();
1047         }
1048 
1049         // NOTE: This one MUST be after EclipseClasspathwriter, and possibly others,
1050         // since currently EclipseClasspathWriter does some magic to detect nested
1051         // output folders and modifies the configuration by adding new (Ant) builders.
1052         // So the .project file must be written AFTER those have run!
1053         new EclipseProjectWriter().init( getLog(), config ).write();
1054 
1055         writeAdditionalConfig();
1056 
1057         getLog().info( Messages.getString( "EclipsePlugin.wrote", new Object[] { //$NON-NLS-1$
1058                                            config.getEclipseProjectName(), eclipseProjectDir.getAbsolutePath() } ) );
1059     }
1060 
1061     private void writeAdditionalConfig()
1062         throws MojoExecutionException
1063     {
1064         if ( additionalConfig != null )
1065         {
1066             for ( int j = 0; j < additionalConfig.length; j++ )
1067             {
1068                 EclipseConfigFile file = additionalConfig[j];
1069                 File projectRelativeFile = new File( eclipseProjectDir, file.getName() );
1070                 if ( projectRelativeFile.isDirectory() )
1071                 {
1072                     // just ignore?
1073                     getLog().warn( Messages.getString( "EclipsePlugin.foundadir", //$NON-NLS-1$
1074                                                        projectRelativeFile.getAbsolutePath() ) );
1075                 }
1076 
1077                 try
1078                 {
1079                     projectRelativeFile.getParentFile().mkdirs();
1080                     if ( file.getContent() == null )
1081                     {
1082                         InputStream inStream;
1083                         if ( file.getLocation() != null )
1084                         {
1085                             inStream = locator.getResourceAsInputStream( file.getLocation() );
1086                         }
1087                         else
1088                         {
1089                             inStream = file.getURL().openConnection().getInputStream();
1090                         }
1091                         OutputStream outStream = new FileOutputStream( projectRelativeFile );
1092                         try
1093                         {
1094                             IOUtil.copy( inStream, outStream );
1095                         }
1096                         finally
1097                         {
1098                             inStream.close();
1099                             outStream.close();
1100                         }
1101                     }
1102                     else
1103                     {
1104                         FileUtils.fileWrite( projectRelativeFile.getAbsolutePath(), file.getContent() );
1105                     }
1106                 }
1107                 catch ( IOException e )
1108                 {
1109                     throw new MojoExecutionException( Messages.getString( "EclipsePlugin.cantwritetofile", //$NON-NLS-1$
1110                                                                           projectRelativeFile.getAbsolutePath() ) );
1111                 }
1112                 catch ( ResourceNotFoundException e )
1113                 {
1114                     throw new MojoExecutionException( Messages.getString( "EclipsePlugin.cantfindresource", //$NON-NLS-1$
1115                                                                           file.getLocation() ) );
1116                 }
1117 
1118             }
1119         }
1120     }
1121 
1122     /**
1123      * Create the <code>EclipseWriterConfig</code> for the specified dependencies.
1124      * 
1125      * @param deps the project dependencies
1126      * @return a configured <code>EclipseWriterConfig</code>
1127      * @throws MojoExecutionException mojo failures.
1128      */
1129     protected final EclipseWriterConfig createEclipseWriterConfig( IdeDependency[] deps )
1130         throws MojoExecutionException
1131     {
1132         File projectBaseDir = executedProject.getFile().getParentFile();
1133 
1134         // build a list of UNIQUE source dirs (both src and resources) to be
1135         // used in classpath and wtpmodules
1136         EclipseSourceDir[] sourceDirs = buildDirectoryList( executedProject, eclipseProjectDir, buildOutputDirectory );
1137 
1138         EclipseWriterConfig config = new EclipseWriterConfig();
1139 
1140         config.setWorkspaceConfiguration( getWorkspaceConfiguration() );
1141 
1142         config.setProjectNameTemplate( getProjectNameTemplate() );
1143 
1144         String projectName = IdeUtils.getProjectName( config.getProjectNameTemplate(), project );
1145 
1146         config.setEclipseProjectName( projectName );
1147 
1148         config.setWtpapplicationxml( wtpapplicationxml );
1149 
1150         config.setWtpVersion( wtpVersionFloat );
1151 
1152         float ajdtVersionFloat;
1153         try
1154         {
1155             ajdtVersionFloat = Float.parseFloat( ajdtVersion );
1156         }
1157         catch ( NumberFormatException e )
1158         {
1159             ajdtVersionFloat = 0.0f;
1160         }
1161 
1162         config.setAjdtVersion( ajdtVersionFloat );
1163 
1164         Set convertedBuildCommands = new LinkedHashSet();
1165 
1166         if ( buildcommands != null )
1167         {
1168             for ( Iterator it = buildcommands.iterator(); it.hasNext(); )
1169             {
1170                 Object cmd = it.next();
1171 
1172                 if ( cmd instanceof BuildCommand )
1173                 {
1174                     convertedBuildCommands.add( cmd );
1175                 }
1176                 else
1177                 {
1178                     convertedBuildCommands.add( new BuildCommand( (String) cmd ) );
1179                 }
1180             }
1181         }
1182 
1183         if ( ajdt )
1184         {
1185             buildAjdtWeaveDeps( deps );
1186             buildAspectjDeps( deps );
1187         }
1188 
1189         config.setBuildCommands( new LinkedList( convertedBuildCommands ) );
1190 
1191         config.setBuildOutputDirectory( buildOutputDirectory );
1192         config.setClasspathContainers( classpathContainers );
1193         config.setDeps( deps );
1194         config.setEclipseProjectDirectory( eclipseProjectDir );
1195         config.setLocalRepository( localRepository );
1196         config.setOSGIManifestFile( manifest );
1197         config.setPde( pde );
1198         config.setProject( project );
1199         config.setProjectBaseDir( projectBaseDir );
1200         config.setProjectnatures( projectnatures );
1201         config.setProjectFacets( additionalProjectFacets );
1202         config.setSourceDirs( sourceDirs );
1203         config.setAddVersionToProjectName( isAddVersionToProjectName() );
1204         config.setPackaging( packaging );
1205 
1206         collectWarContextRootsFromReactorEarConfiguration( config );
1207 
1208         return config;
1209     }
1210 
1211     /**
1212      * If this is a war module peek into the reactor an search for an ear module that defines the context root of this
1213      * module.
1214      * 
1215      * @param config config to save the context root.
1216      */
1217     private void collectWarContextRootsFromReactorEarConfiguration( EclipseWriterConfig config )
1218     {
1219         if ( reactorProjects != null && wtpContextName == null
1220             && Constants.PROJECT_PACKAGING_WAR.equals( project.getPackaging() ) )
1221         {
1222             for ( Iterator iter = reactorProjects.iterator(); iter.hasNext(); )
1223             {
1224                 MavenProject reactorProject = (MavenProject) iter.next();
1225 
1226                 if ( Constants.PROJECT_PACKAGING_EAR.equals( reactorProject.getPackaging() ) )
1227                 {
1228                     Xpp3Dom[] warDefinitions =
1229                         IdeUtils.getPluginConfigurationDom( reactorProject, JeeUtils.ARTIFACT_MAVEN_EAR_PLUGIN,
1230                                                             new String[] { "modules", "webModule" } );
1231                     for ( int index = 0; index < warDefinitions.length; index++ )
1232                     {
1233                         Xpp3Dom groupId = warDefinitions[index].getChild( "groupId" );
1234                         Xpp3Dom artifactId = warDefinitions[index].getChild( "artifactId" );
1235                         Xpp3Dom contextRoot = warDefinitions[index].getChild( "contextRoot" );
1236                         if ( groupId != null && artifactId != null && contextRoot != null && groupId.getValue() != null
1237                             && artifactId.getValue() != null && contextRoot.getValue() != null )
1238                         {
1239                             getLog().info(
1240                                            "Found context root definition for " + groupId.getValue() + ":"
1241                                                + artifactId.getValue() + " " + contextRoot.getValue() );
1242                             if ( project.getArtifactId().equals( artifactId.getValue() )
1243                                 && project.getGroupId().equals( groupId.getValue() ) )
1244                             {
1245                                 config.setContextName( contextRoot.getValue() );
1246                             }
1247                         }
1248                         else
1249                         {
1250                             getLog().info(
1251                                            "Found incomplete ear configuration in " + reactorProject.getGroupId() + ":"
1252                                                + reactorProject.getGroupId() + " found "
1253                                                + warDefinitions[index].toString() );
1254                         }
1255                     }
1256                 }
1257             }
1258         }
1259         if ( config.getContextName() == null && Constants.PROJECT_PACKAGING_WAR.equals( project.getPackaging() ) )
1260         {
1261             if ( wtpContextName == null )
1262             {
1263                 config.setContextName( project.getArtifactId() );
1264             }
1265             else
1266             {
1267                 config.setContextName( wtpContextName );
1268             }
1269         }
1270     }
1271 
1272     /**
1273      * Write any extra configuration information for the Eclipse project. This is an extension point, called before the
1274      * main configurations are written. <br/> <b> NOTE: This could change the config! </b>
1275      * 
1276      * @param config
1277      * @throws MojoExecutionException
1278      */
1279     protected void writeConfigurationExtras( EclipseWriterConfig config )
1280         throws MojoExecutionException
1281     {
1282         // extension point.
1283     }
1284 
1285     private void assertNotEmpty( String string, String elementName )
1286         throws MojoExecutionException
1287     {
1288         if ( string == null )
1289         {
1290             throw new MojoExecutionException( Messages.getString( "EclipsePlugin.missingelement", elementName ) ); //$NON-NLS-1$
1291         }
1292     }
1293     
1294     /**
1295      * Fill getProjectnatures() with values.
1296      * <p>
1297      * Subclasses should call super and then calculate their own additions and insert them via
1298      * <code>getProjectnatures().addAll()</code>.
1299      * 
1300      * @param packaging the pom's packaging
1301      */    
1302     protected void fillDefaultNatures( String packaging )
1303     {
1304         projectnatures = new ArrayList();
1305 
1306         if ( wtpVersionFloat >= 1.0f )
1307         {
1308             projectnatures.add( NATURE_WST_FACET_CORE_NATURE ); // WTP 1.0 nature
1309         }
1310 
1311         if ( isJavaProject )
1312         {
1313             if ( ajdt )
1314             {
1315                 projectnatures.add( NATURE_AJDT_CORE_JAVA );
1316             }
1317 
1318             projectnatures.add( NATURE_JDT_CORE_JAVA );
1319         }
1320 
1321         if ( wtpVersionFloat >= 0.7f )
1322         {
1323             projectnatures.add( NATURE_WST_MODULE_CORE_NATURE ); // WTP 0.7/1.0 nature
1324 
1325             if ( isJavaProject )
1326             {
1327                 projectnatures.add( NATURE_JEM_WORKBENCH_JAVA_EMF ); // WTP 0.7/1.0 nature
1328             }
1329         }
1330 
1331         if ( pde )
1332         {
1333             projectnatures.add( NATURE_PDE_PLUGIN );
1334         }
1335 
1336     }
1337 
1338     /**
1339      * Fill getClasspathContainers() with values.
1340      * <p>
1341      * Subclasses should call super and then calculate their own additions and insert them via
1342      * <code>getClasspathContainers().addAll()</code>.
1343      * 
1344      * @param packaging the pom's packaging
1345      */
1346     protected void fillDefaultClasspathContainers( String packaging )
1347     {
1348         classpathContainers = new ArrayList();
1349 
1350         if ( getWorkspaceConfiguration().getDefaultClasspathContainer() != null )
1351         {
1352             getLog().info(
1353                            "Adding default classpath container: "
1354                                + getWorkspaceConfiguration().getDefaultClasspathContainer() );
1355             classpathContainers.add( getWorkspaceConfiguration().getDefaultClasspathContainer() );
1356         }
1357         if ( pde )
1358         {
1359             classpathContainers.add( REQUIRED_PLUGINS_CONTAINER );
1360         }
1361 
1362         if ( ajdt )
1363         {
1364             classpathContainers.add( ASPECTJ_RT_CONTAINER );
1365         }
1366     }
1367 
1368     /**
1369      * Fill getBuildcommands() with values.
1370      * <p>
1371      * Subclasses should call super and then calculate their own additions and insert them via
1372      * <code>getBuildcommands().addAll()</code>.
1373      * 
1374      * @param packaging the pom's packaging
1375      */
1376     protected void fillDefaultBuilders( String packaging )
1377     {
1378         buildcommands = new ArrayList();
1379 
1380         if ( wtpVersionFloat == 0.7f )
1381         {
1382             buildcommands.add( new BuildCommand( BUILDER_WST_COMPONENT_STRUCTURAL ) ); // WTP 0.7 builder
1383         }
1384 
1385         if ( isJavaProject )
1386         {
1387             if ( ajdt )
1388             {
1389                 buildcommands.add( new BuildCommand( BUILDER_AJDT_CORE_JAVA ) );
1390             }
1391             else
1392             {
1393                 buildcommands.add( new BuildCommand( BUILDER_JDT_CORE_JAVA ) );
1394             }
1395         }
1396 
1397         if ( wtpVersionFloat >= 1.5f )
1398         {
1399             buildcommands.add( new BuildCommand( BUILDER_WST_FACET ) ); // WTP 1.5 builder
1400         }
1401 
1402         if ( wtpVersionFloat >= 0.7f )
1403         {
1404             buildcommands.add( new BuildCommand( BUILDER_WST_VALIDATION ) ); // WTP 0.7/1.0 builder
1405         }
1406 
1407         if ( wtpVersionFloat == 0.7f )
1408         {
1409             // WTP 0.7 builder
1410             buildcommands.add( new BuildCommand( BUILDER_WST_COMPONENT_STRUCTURAL_DEPENDENCY_RESOLVER ) );
1411         }
1412 
1413         if ( pde )
1414         {
1415             buildcommands.add( new BuildCommand( BUILDER_PDE_MANIFEST ) );
1416             buildcommands.add( new BuildCommand( BUILDER_PDE_SCHEMA ) );
1417         }
1418     }
1419 
1420     public final EclipseSourceDir[] buildDirectoryList( MavenProject project, File basedir, File buildOutputDirectory )
1421         throws MojoExecutionException
1422     {
1423         File projectBaseDir = project.getFile().getParentFile();
1424 
1425         String mainOutput = IdeUtils.toRelativeAndFixSeparator( projectBaseDir, buildOutputDirectory, false );
1426 
1427         // If using the standard output location, don't mix the test output into it.
1428         String testOutput = null;
1429         boolean useStandardOutputDir =
1430             buildOutputDirectory.equals( new File( project.getBuild().getOutputDirectory() ) );
1431         if ( useStandardOutputDir )
1432         {
1433             getLog().debug(
1434                             "testOutput toRelativeAndFixSeparator " + projectBaseDir + " , "
1435                                 + project.getBuild().getTestOutputDirectory() );
1436             testOutput =
1437                 IdeUtils.toRelativeAndFixSeparator( projectBaseDir,
1438                                                     new File( project.getBuild().getTestOutputDirectory() ), false );
1439             getLog().debug( "testOutput after toRelative : " + testOutput );
1440         }
1441 
1442         Set mainDirectories = new LinkedHashSet();
1443 
1444         extractSourceDirs( mainDirectories, project.getCompileSourceRoots(), basedir, projectBaseDir, false, null );
1445 
1446         extractResourceDirs( mainDirectories, project.getBuild().getResources(), basedir, projectBaseDir, false,
1447                              mainOutput );
1448 
1449         Set testDirectories = new LinkedHashSet();
1450 
1451         extractSourceDirs( testDirectories, project.getTestCompileSourceRoots(), basedir, projectBaseDir, true,
1452                            testOutput );
1453 
1454         extractResourceDirs( testDirectories, project.getBuild().getTestResources(), basedir, projectBaseDir, true,
1455                              testOutput );
1456 
1457         // avoid duplicated entries
1458         Set directories = new LinkedHashSet();
1459 
1460         // NOTE: Since MNG-3118, test classes come before main classes
1461         boolean testBeforeMain = isMavenVersion( "[2.0.8,)" );
1462 
1463         if ( testBeforeMain )
1464         {
1465             directories.addAll( testDirectories );
1466             directories.removeAll( mainDirectories );
1467             directories.addAll( mainDirectories );
1468         }
1469         else
1470         {
1471             directories.addAll( mainDirectories );
1472             directories.addAll( testDirectories );
1473         }
1474         if ( ajdt )
1475             extractAspectDirs( directories, project, basedir, projectBaseDir, testOutput );
1476         return (EclipseSourceDir[]) directories.toArray( new EclipseSourceDir[directories.size()] );
1477     }
1478 
1479     private void extractSourceDirs( Set directories, List sourceRoots, File basedir, File projectBaseDir, boolean test,
1480                                     String output )
1481         throws MojoExecutionException
1482     {
1483         for ( Iterator it = sourceRoots.iterator(); it.hasNext(); )
1484         {
1485 
1486             File sourceRootFile = new File( (String) it.next() );
1487 
1488             if ( sourceRootFile.isDirectory() )
1489             {
1490                 String sourceRoot =
1491                     IdeUtils.toRelativeAndFixSeparator( projectBaseDir, sourceRootFile,
1492                                                         !projectBaseDir.equals( basedir ) );
1493 
1494                 directories.add( new EclipseSourceDir( sourceRoot, output, false, test, null, null, false ) );
1495             }
1496         }
1497     }
1498 
1499     final void extractResourceDirs( Set directories, List resources, File basedir, File workspaceProjectBaseDir,
1500                               boolean test, final String output )
1501         throws MojoExecutionException
1502     {
1503         for ( Iterator it = resources.iterator(); it.hasNext(); )
1504         {
1505             Resource resource = (Resource) it.next();
1506 
1507             getLog().debug( "Processing resource dir: " + resource.getDirectory() );
1508 
1509             String includePattern = null;
1510             String excludePattern = null;
1511 
1512             if ( resource.getIncludes().size() != 0 )
1513             {
1514                 includePattern = StringUtils.join( resource.getIncludes().iterator(), "|" );
1515             }
1516 
1517             if ( resource.getExcludes().size() != 0 )
1518             {
1519                 excludePattern = StringUtils.join( resource.getExcludes().iterator(), "|" );
1520             }
1521 
1522             // TODO: figure out how to merge if the same dir is specified twice
1523             // with different in/exclude patterns.
1524 
1525             File resourceDirectory = new File( /* basedir, */resource.getDirectory() );
1526 
1527             if ( !resourceDirectory.exists() || !resourceDirectory.isDirectory() )
1528             {
1529                 getLog().debug( "Resource dir: " + resourceDirectory + " either missing or not a directory." );
1530                 continue;
1531             }
1532 
1533             String resourceDir =
1534                 IdeUtils.toRelativeAndFixSeparator( workspaceProjectBaseDir, resourceDirectory,
1535                                                     !workspaceProjectBaseDir.equals( basedir ) );
1536             String thisOutput = output;
1537             if ( thisOutput != null )
1538             {
1539                 // sometimes thisOutput is already an absolute path
1540                 File outputFile = new File( thisOutput );
1541                 if ( !outputFile.isAbsolute() )
1542                 {
1543                     outputFile = new File( workspaceProjectBaseDir, thisOutput );
1544                 }
1545                 // create output dir if it doesn't exist
1546                 outputFile.mkdirs();
1547 
1548                 if ( !StringUtils.isEmpty( resource.getTargetPath() ) )
1549                 {
1550                     outputFile = new File( outputFile, resource.getTargetPath() );
1551                     // create output dir if it doesn't exist
1552                     outputFile.mkdirs();
1553                 }
1554 
1555                 getLog().debug(
1556                                 "Making relative and fixing separator: { " + workspaceProjectBaseDir + ", "
1557                                     + outputFile + ", false }." );
1558                 thisOutput = IdeUtils.toRelativeAndFixSeparator( workspaceProjectBaseDir, outputFile, false );
1559             }
1560 
1561             getLog().debug(
1562                             "Adding eclipse source dir: { " + resourceDir + ", " + thisOutput + ", true, " + test
1563                                 + ", " + includePattern + ", " + excludePattern + " }." );
1564 
1565             directories.add( new EclipseSourceDir( resourceDir, thisOutput, true, test, includePattern, excludePattern,
1566                                                    resource.isFiltering() ) );
1567         }
1568     }
1569 
1570     private void extractAspectDirs( Set directories, MavenProject project, File basedir, File projectBaseDir,
1571                                     String testOutput )
1572         throws MojoExecutionException
1573     {
1574         Xpp3Dom configuration = getAspectjConfiguration( project );
1575         if ( configuration != null )
1576         {
1577             String aspectDirectory = DEFAULT_ASPECT_DIRECTORY;
1578             Xpp3Dom aspectDirectoryElement = configuration.getChild( ASPECT_DIRECTORY );
1579             if ( aspectDirectoryElement != null )
1580             {
1581                 aspectDirectory = aspectDirectoryElement.getValue();
1582             }
1583 
1584             File aspectDirectoryFile = new File( basedir, aspectDirectory );
1585             if ( aspectDirectoryFile.exists() && aspectDirectoryFile.isDirectory() )
1586             {
1587                 String sourceRoot =
1588                     IdeUtils.toRelativeAndFixSeparator( projectBaseDir, aspectDirectoryFile,
1589                                                         !projectBaseDir.equals( basedir ) );
1590 
1591                 directories.add( new EclipseSourceDir( sourceRoot, null, false, false, null, null, false ) );
1592             }
1593 
1594             String testAspectDirectory = DEFAULT_TEST_ASPECT_DIRECTORY;
1595             Xpp3Dom testAspectDirectoryElement = configuration.getChild( TEST_ASPECT_DIRECTORY );
1596             if ( testAspectDirectoryElement != null )
1597             {
1598                 testAspectDirectory = testAspectDirectoryElement.getValue();
1599             }
1600 
1601             File testAspectDirectoryFile = new File( basedir, testAspectDirectory );
1602             if ( testAspectDirectoryFile.exists() && testAspectDirectoryFile.isDirectory() )
1603             {
1604                 String sourceRoot =
1605                     IdeUtils.toRelativeAndFixSeparator( projectBaseDir, testAspectDirectoryFile,
1606                                                         !projectBaseDir.equals( basedir ) );
1607 
1608                 directories.add( new EclipseSourceDir( sourceRoot, testOutput, false, true, null, null, false ) );
1609             }
1610         }
1611     }
1612 
1613     private boolean enableAjdt( MavenProject project )
1614     {
1615         boolean enable = false;
1616         List buildPlugins = project.getBuildPlugins();
1617         for ( Iterator it = buildPlugins.iterator(); it.hasNext(); )
1618         {
1619             Plugin plugin = (Plugin) it.next();
1620             if ( plugin.getGroupId().equals( ORG_CODEHAUS_MOJO )
1621                 && plugin.getArtifactId().equals( ASPECTJ_MAVEN_PLUGIN ) )
1622             {
1623                 enable = true;
1624                 break;
1625             }
1626         }
1627 
1628         return enable;
1629     }
1630 
1631     private Xpp3Dom getAspectjConfiguration( MavenProject project )
1632     {
1633         Xpp3Dom configuration = null;
1634         List buildPlugins = project.getBuildPlugins();
1635         for ( Iterator it = buildPlugins.iterator(); it.hasNext(); )
1636         {
1637             Plugin plugin = (Plugin) it.next();
1638             if ( plugin.getGroupId().equals( ORG_CODEHAUS_MOJO )
1639                 && plugin.getArtifactId().equals( ASPECTJ_MAVEN_PLUGIN ) )
1640             {
1641                 configuration = (Xpp3Dom) plugin.getConfiguration();
1642                 break;
1643             }
1644         }
1645 
1646         return configuration;
1647     }
1648 
1649     private void buildAspectjDeps( IdeDependency[] deps )
1650         throws MojoExecutionException
1651     {
1652         Xpp3Dom configuration = getAspectjConfiguration( executedProject );
1653         if ( configuration != null )
1654         {
1655             Xpp3Dom aspectLibrariesParent = configuration.getChild( ASPECT_LIBRARIES );
1656             if ( aspectLibrariesParent != null )
1657             {
1658                 Xpp3Dom[] aspectLibraries = aspectLibrariesParent.getChildren( ASPECT_LIBRARY );
1659                 outerLoop: for ( int i = 0; i < aspectLibraries.length; i++ )
1660                 {
1661                     String artifactId = aspectLibraries[i].getChild( POM_ELT_ARTIFACT_ID ).getValue();
1662                     String groupId = aspectLibraries[i].getChild( POM_ELT_GROUP_ID ).getValue();
1663                     for ( int j = 0; j < deps.length; j++ )
1664                     {
1665                         if ( deps[j].getArtifactId().equals( artifactId ) && deps[j].getGroupId().equals( groupId ) )
1666                         {
1667                             deps[j].setAjdtDependency( true );
1668                             continue outerLoop;
1669                         }
1670                     }
1671 
1672                     throw new MojoExecutionException( "AspectLibrary is not a dependency of project" );
1673                 }
1674             }
1675         }
1676     }
1677 
1678     private void buildAjdtWeaveDeps( IdeDependency[] deps )
1679         throws MojoExecutionException
1680     {
1681         Xpp3Dom configuration = getAspectjConfiguration( executedProject );
1682         if ( configuration != null )
1683         {
1684             Xpp3Dom weaveDependenciesParent = configuration.getChild( WEAVE_DEPENDENCIES );
1685             if ( weaveDependenciesParent != null )
1686             {
1687                 Xpp3Dom[] weaveDependencies = weaveDependenciesParent.getChildren( WEAVE_DEPENDENCY );
1688                 outerLoop: for ( int i = 0; i < weaveDependencies.length; i++ )
1689                 {
1690                     String artifactId = weaveDependencies[i].getChild( POM_ELT_ARTIFACT_ID ).getValue();
1691                     String groupId = weaveDependencies[i].getChild( POM_ELT_GROUP_ID ).getValue();
1692                     for ( int j = 0; j < deps.length; j++ )
1693                     {
1694                         if ( deps[j].getArtifactId().equals( artifactId ) && deps[j].getGroupId().equals( groupId ) )
1695                         {
1696                             deps[j].setAjdtWeaveDependency( true );
1697                             continue outerLoop;
1698                         }
1699                     }
1700 
1701                     throw new MojoExecutionException( "WeaveDependency is not a dependency of project" );
1702                 }
1703             }
1704         }
1705     }
1706     
1707     /**
1708      * {@inheritDoc}
1709      */
1710     public String getProjectNameForArifact( Artifact artifact )
1711     {
1712         IdeDependency[] workspaceArtefacts = getWorkspaceArtefacts();
1713         for ( int index = 0; workspaceArtefacts != null && index < workspaceArtefacts.length; index++ )
1714         {
1715             IdeDependency workspaceArtefact = workspaceArtefacts[index];
1716             if ( workspaceArtefact.isAddedToClasspath()
1717                 && workspaceArtefact.getGroupId().equals( artifact.getGroupId() )
1718                 && workspaceArtefact.getArtifactId().equals( artifact.getArtifactId() ) )
1719             {
1720                 if ( workspaceArtefact.getVersion().equals( artifact.getVersion() ) )
1721                 {
1722                     return workspaceArtefact.getEclipseProjectName();
1723                 }
1724             }
1725         }
1726         MavenProject reactorProject = getReactorProject( artifact );
1727         if ( reactorProject != null ) {
1728             return IdeUtils.getProjectName( getProjectNameTemplateForMavenProject( reactorProject ), artifact );
1729         }
1730         return IdeUtils.getProjectName( getProjectNameTemplate(), artifact );
1731     }
1732     
1733     /**
1734      * @param mavenProject the project to get the projectNameTemplate configuration from
1735      * @return the projectNameTemplate configuration from the specified MavenProject 
1736      */
1737     private String getProjectNameTemplateForMavenProject( MavenProject mavenProject )
1738     {
1739         String projectNameTemplate = null;
1740         boolean addVersionToProjectName = false;
1741         boolean addGroupIdToProjectName = false;
1742 
1743         Build build = mavenProject.getBuild();
1744         if ( build != null )
1745         {
1746             Plugin plugin = (Plugin) build.getPluginsAsMap().get( "org.apache.maven.plugins:maven-eclipse-plugin" );
1747             if ( plugin != null )
1748             {
1749                 Xpp3Dom config = (Xpp3Dom) plugin.getConfiguration();
1750                 if ( config != null )
1751                 {
1752                     Xpp3Dom projectNameTemplateNode = config.getChild( "projectNameTemplate" );
1753                     if ( projectNameTemplateNode != null )
1754                     {
1755                         projectNameTemplate = projectNameTemplateNode.getValue();
1756                     }
1757                     Xpp3Dom addVersionToProjectNameNode = config.getChild( "addVersionToProjectName" );
1758                     addVersionToProjectName = addVersionToProjectNameNode != null;
1759                     Xpp3Dom addGroupIdToProjectNameNode = config.getChild( "addGroupIdToProjectName" );
1760                     addGroupIdToProjectName = addGroupIdToProjectNameNode != null;
1761                 }
1762             }
1763         }
1764         return IdeUtils.calculateProjectNameTemplate(projectNameTemplate, addVersionToProjectName, addGroupIdToProjectName, getLog());
1765     }
1766 
1767     /**
1768      * {@inheritDoc}
1769      */
1770     protected final IdeDependency[] getWorkspaceArtefacts()
1771     {
1772         return getWorkspaceConfiguration().getWorkspaceArtefacts();
1773     }
1774 
1775     public final WorkspaceConfiguration getWorkspaceConfiguration()
1776     {
1777         if ( workspaceConfiguration == null )
1778         {
1779             workspaceConfiguration = new WorkspaceConfiguration();
1780             locateWorkspace();
1781             getLog().info( Messages.getString( "EclipsePlugin.workspace", workspace ) );
1782             workspaceConfiguration.setWorkspaceDirectory( workspace );
1783 
1784             new ReadWorkspaceLocations().init( getLog(), workspaceConfiguration, project, wtpdefaultserver );
1785         }
1786         return workspaceConfiguration;
1787     }
1788 
1789     /**
1790      * If workspace is not defined, then attempt to locate it by checking up the directory hierarchy.
1791      */
1792     private void locateWorkspace()
1793     {
1794         if ( workspace == null )
1795         {
1796             File currentWorkingDirectory = new File( "." ).getAbsoluteFile();
1797             while ( currentWorkingDirectory != null )
1798             {
1799                 File metadataDirectory = new File( currentWorkingDirectory, ".metadata" );
1800                 logger.debug( "Checking for eclipse workspace at " + currentWorkingDirectory );
1801                 if ( metadataDirectory.exists() && metadataDirectory.isDirectory() )
1802                 {
1803                     logger.debug( "  Found workspace at " + currentWorkingDirectory );
1804                     workspace = currentWorkingDirectory;
1805                     return;
1806                 }
1807                 currentWorkingDirectory = currentWorkingDirectory.getParentFile();
1808             }
1809         }
1810     }
1811 
1812     public final List getExcludes()
1813     {
1814         return excludes;
1815     }
1816 
1817     /**
1818      * Utility method that locates a project in the workspace for the given artifact.
1819      * 
1820      * @param artifact the artifact a project should produce.
1821      * @return <code>true</code> if the artifact is produced by a reactor projectart.
1822      */
1823     private boolean isAvailableAsAWorkspaceProject( Artifact artifact )
1824     {
1825         IdeDependency[] workspaceArtefacts = getWorkspaceArtefacts();
1826         for ( int index = 0; workspaceArtefacts != null && index < workspaceArtefacts.length; index++ )
1827         {
1828             IdeDependency workspaceArtefact = workspaceArtefacts[index];
1829             if ( workspaceArtefact.getGroupId().equals( artifact.getGroupId() )
1830                 && workspaceArtefact.getArtifactId().equals( artifact.getArtifactId() ) )
1831             {
1832                 if ( workspaceArtefact.getVersion().equals( artifact.getVersion() ) )
1833                 {
1834                     workspaceArtefact.setAddedToClasspath( true );
1835                     getLog().debug( "Using workspace project: " + workspaceArtefact.getEclipseProjectName() );
1836                     return true;
1837                 }
1838                 else
1839                 {
1840                     getLog().info(
1841                                    "Artifact "
1842                                        + artifact.getId()
1843                                        + " already available as a workspace project, but with different version. Expected: "
1844                                        + artifact.getVersion() + ", found: " + workspaceArtefact.getVersion() );
1845                 }
1846             }
1847         }
1848         return false;
1849     }
1850 
1851     /**
1852      * Checks if jar has to be resolved for the given artifact
1853      * 
1854      * @param art the artifact to check
1855      * @return true if resolution should happen
1856      */
1857     protected final boolean hasToResolveJar( Artifact art )
1858     {
1859         return !( getUseProjectReferences() && isAvailableAsAReactorProject( art ) )
1860             || ( limitProjectReferencesToWorkspace && !( getUseProjectReferences() && isAvailableAsAWorkspaceProject( art ) ) );
1861     }
1862 
1863     /**
1864      * Checks if a projects reference has to be used for the given artifact
1865      * 
1866      * @param art the artifact to check
1867      * @return true if a project reference has to be used.
1868      */
1869     protected final boolean useProjectReference( Artifact art )
1870     {
1871         boolean isReactorProject = getUseProjectReferences() && isAvailableAsAReactorProject( art );
1872         boolean isWorkspaceProject = getUseProjectReferences() && isAvailableAsAWorkspaceProject( art );
1873         return ( isReactorProject && !limitProjectReferencesToWorkspace ) || // default
1874             ( limitProjectReferencesToWorkspace && isWorkspaceProject ) || // limitProjectReferencesToWorkspace
1875             ( !isReactorProject && isWorkspaceProject ); // default + workspace projects
1876     }
1877 }