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