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