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