View Javadoc
1   package org.apache.maven.plugin.eclipse.writers.wtp;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   * 
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   * 
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  
23  import java.io.File;
24  import java.io.FileInputStream;
25  import java.io.FileNotFoundException;
26  import java.io.FileOutputStream;
27  import java.io.IOException;
28  import java.io.InputStreamReader;
29  import java.io.OutputStreamWriter;
30  import java.io.Reader;
31  import java.io.Writer;
32  
33  import org.apache.maven.artifact.repository.ArtifactRepository;
34  import org.apache.maven.plugin.MojoExecutionException;
35  import org.apache.maven.plugin.eclipse.Constants;
36  import org.apache.maven.plugin.eclipse.EclipseSourceDir;
37  import org.apache.maven.plugin.ide.IdeDependency;
38  import org.apache.maven.plugin.ide.IdeUtils;
39  import org.apache.maven.plugin.ide.JeeUtils;
40  import org.codehaus.plexus.util.FileUtils;
41  import org.codehaus.plexus.util.IOUtil;
42  import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter;
43  import org.codehaus.plexus.util.xml.XMLWriter;
44  import org.codehaus.plexus.util.xml.Xpp3Dom;
45  import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
46  import org.codehaus.plexus.util.xml.Xpp3DomWriter;
47  
48  /**
49   * This writer creates the application.xml and the .modulemaps files for RAD6 the the META-INF directory in the project
50   * root. this is where RAD6 requires the files to be. These will be independent of the real application.xml witch will
51   * be generated the stad. maven way.
52   * 
53   * @author <a href="mailto:nir@cfc.at">Richard van Nieuwenhoven</a>
54   */
55  public class EclipseWtpApplicationXMLWriter
56      extends AbstractWtpResourceWriter
57  {
58  
59      private static final String APPLICATION_XML_APPLICATION = "application";
60  
61      private static final String APPLICATION_XML_CONTEXT_ROOT = "context-root";
62  
63      private static final String APPLICATION_XML_DESCRIPTION = "description";
64  
65      private static final String APPLICATION_XML_DISPLAY_NAME = "display-name";
66  
67      private static final String APPLICATION_XML_FILENAME = "application.xml";
68  
69      private static final String APPLICATION_XML_MODULE = "module";
70  
71      private static final String APPLICATION_XML_WEB = "web";
72  
73      private static final String APPLICATION_XML_WEB_URI = "web-uri";
74  
75      private static final String HREF = "href";
76  
77      private static final String ID = "id";
78  
79      private static final String MODULEMAP_EARPROJECT_MAP = "modulemap:EARProjectMap";
80  
81      private static final String MODULEMAPS_APPLICATION_EJB_MODULE = "application:EjbModule";
82  
83      private static final String MODULEMAPS_APPLICATION_WEB_MODULE = "application:WebModule";
84  
85      private static final String MODULEMAPS_FILENAME = ".modulemaps";
86  
87      private static final String MODULEMAPS_MAPPINGS = "mappings";
88  
89      private static final String MODULEMAPS_PROJECT_NAME = "projectName";
90  
91      private static final String MODULEMAPS_UTILITY_JARMAPPINGS = "utilityJARMappings";
92  
93      private static final String URI = "uri";
94  
95      private static final String VERSION = "version";
96  
97      private static final String XMI_ID = "xmi:id";
98  
99      private static final String XMI_TYPE = "xmi:type";
100 
101     private static final String XMI_VERSION = "xmi:version";
102 
103     private static final String XMLNS = "xmlns";
104 
105     private static final String XMLNS_APPLICATION = "xmlns:application";
106 
107     private static final String XMLNS_MODULEMAP = "xmlns:modulemap";
108 
109     private static final String XMLNS_SCHEMA_LOCATION = "xmlns:schemaLocation";
110 
111     private static final String XSI_SCHEMA_LOCATION = "xsi:schemaLocation";
112 
113     private static final String XMLNS_XMI = "xmlns:xmi";
114 
115     private static final String XMLNS_XSI = "xmlns:xsi";
116 
117     private Xpp3Dom[] applicationXmlDomChildren;
118 
119     private Xpp3Dom[] modulemapsXmlDomChildren;
120 
121     private Xpp3Dom[] webModulesFromPoms;
122 
123     /**
124      * write the application.xml and the .modulemaps file to the META-INF directory.
125      * 
126      * @see AbstractWtpResourceWriter#write(EclipseSourceDir[], ArtifactRepository, File)
127      * @throws MojoExecutionException when writing the config files was not possible
128      */
129     public void write()
130         throws MojoExecutionException
131     {
132         String packaging = this.config.getProject().getPackaging();
133         if ( Constants.PROJECT_PACKAGING_EAR.equalsIgnoreCase( packaging ) )
134         {
135             File applicationXmlFile =
136                 new File( this.config.getEclipseProjectDirectory(), "target" + File.separator + "eclipseEar"
137                     + File.separator + "META-INF" + File.separator
138                     + EclipseWtpApplicationXMLWriter.APPLICATION_XML_FILENAME );
139             // create the directory structiure for eclipse deployment
140             applicationXmlFile.getParentFile().mkdirs();
141             // copy all deployment files to the eclipse deployment
142             copyApplicationFiles();
143             // delete any existing application.xml so that it will be
144             // overwritten.
145             applicationXmlFile.delete();
146 
147             Xpp3Dom applicationXmlDom = readXMLFile( applicationXmlFile );
148             if ( applicationXmlDom == null )
149             {
150                 applicationXmlDom = createNewApplicationXml();
151             }
152             this.applicationXmlDomChildren =
153                 applicationXmlDom.getChildren( EclipseWtpApplicationXMLWriter.APPLICATION_XML_MODULE );
154 
155             File modulemapsXmlFile =
156                 new File( this.config.getEclipseProjectDirectory(), "target" + File.separator + "eclipseEar"
157                     + File.separator + "META-INF" + File.separator + EclipseWtpApplicationXMLWriter.MODULEMAPS_FILENAME );
158             Xpp3Dom modulemapsXmlDom = readXMLFile( modulemapsXmlFile );
159             if ( modulemapsXmlDom == null )
160             {
161                 modulemapsXmlDom = createNewModulemaps();
162             }
163             this.modulemapsXmlDomChildren = modulemapsXmlDom.getChildren();
164 
165             this.webModulesFromPoms =
166                 IdeUtils.getPluginConfigurationDom( config.getProject(), JeeUtils.ARTIFACT_MAVEN_EAR_PLUGIN,
167                                                     new String[] { "modules", "webModule" } );
168 
169             IdeDependency[] deps = this.config.getDeps();
170             for (IdeDependency dep : deps) {
171                 updateApplicationXml(applicationXmlDom, modulemapsXmlDom, dep);
172             }
173 
174             removeUnusedEntries( applicationXmlDom, modulemapsXmlDom );
175 
176             writePrettyXmlFile( applicationXmlFile, applicationXmlDom );
177             writePrettyXmlFile( modulemapsXmlFile, modulemapsXmlDom );
178         }
179     }
180 
181     /**
182      * Copy all files from application directory to the target eclipseEar directory.
183      * 
184      * @throws MojoExecutionException wenn an error occures during file copieing
185      */
186     private void copyApplicationFiles()
187         throws MojoExecutionException
188     {
189         try
190         {
191             File applicationDirectory =
192                 new File( this.config.getEclipseProjectDirectory(), "src" + File.separator + "main" + File.separator
193                     + "application" );
194             File eclipseApplicationDirectory =
195                 new File( this.config.getEclipseProjectDirectory(), "target" + File.separator + "eclipseEar" );
196             copyDirectoryStructure( applicationDirectory, eclipseApplicationDirectory );
197         }
198         catch ( IOException e )
199         {
200             throw new MojoExecutionException( "could not copy files the the eclipseEar directory", e );
201         }
202     }
203 
204     /**
205      * Copies a entire directory structure without scm files. Note:
206      * <ul>
207      * <li>It will include empty directories.
208      * <li>The <code>sourceDirectory</code> must exists.
209      * </ul>
210      * 
211      * @param sourceDirectory
212      * @param destinationDirectory
213      * @throws IOException
214      */
215     public static void copyDirectoryStructure( File sourceDirectory, File destinationDirectory )
216         throws IOException
217     {
218         if ( !sourceDirectory.exists() )
219         {
220             return;
221         }
222 
223         File[] files = sourceDirectory.listFiles();
224 
225         String sourcePath = sourceDirectory.getAbsolutePath();
226 
227         for (File file : files) {
228             String dest = file.getAbsolutePath();
229 
230             dest = dest.substring(sourcePath.length() + 1);
231 
232             File destination = new File(destinationDirectory, dest);
233 
234             if (file.isFile()) {
235                 destination = destination.getParentFile();
236 
237                 FileUtils.copyFileToDirectory(file, destination);
238             } else if (file.isDirectory() && !file.getName().equals(".svn") && !file.getName().equals("CVS")) {
239                 if (!destination.exists() && !destination.mkdirs()) {
240                     throw new IOException("Could not create destination directory '" + destination.getAbsolutePath()
241                             + "'.");
242                 }
243 
244                 copyDirectoryStructure(file, destination);
245             }
246         }
247     }
248 
249     /**
250      * there is no existing application.xml file so create a new one.
251      * 
252      * @return the domtree representing the contents of application.xml
253      */
254     private Xpp3Dom createNewApplicationXml()
255     {
256         Xpp3Dom result = new Xpp3Dom( EclipseWtpApplicationXMLWriter.APPLICATION_XML_APPLICATION );
257         result.setAttribute( EclipseWtpApplicationXMLWriter.ID, "Application_ID" );
258         result.setAttribute( EclipseWtpApplicationXMLWriter.VERSION, "1.4" );
259         result.setAttribute( EclipseWtpApplicationXMLWriter.XMLNS, "http://java.sun.com/xml/ns/j2ee" );
260         result.setAttribute( EclipseWtpApplicationXMLWriter.XMLNS_XSI, "http://www.w3.org/2001/XMLSchema-instance" );
261 
262         // special case for development websphere's ....
263         String locationAttribute;
264         if ( this.config.getWorkspaceConfiguration().getWebsphereVersion() != null )
265         {
266             locationAttribute = EclipseWtpApplicationXMLWriter.XSI_SCHEMA_LOCATION;
267         }
268         else
269         {
270             locationAttribute = EclipseWtpApplicationXMLWriter.XMLNS_SCHEMA_LOCATION;
271         }
272         result.setAttribute( locationAttribute,
273                              "http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/application_1_4.xsd" );
274         result.addChild( new Xpp3Dom( EclipseWtpApplicationXMLWriter.APPLICATION_XML_DESCRIPTION ) );
275         Xpp3Dom name = new Xpp3Dom( EclipseWtpApplicationXMLWriter.APPLICATION_XML_DISPLAY_NAME );
276         name.setValue( this.config.getEclipseProjectName() );
277         result.addChild( name );
278         return result;
279     }
280 
281     /**
282      * there is no existing .modulemaps file so create a new one.
283      * 
284      * @return the domtree representing the contents of the .modulemaps file
285      */
286     private Xpp3Dom createNewModulemaps()
287     {
288         Xpp3Dom result = new Xpp3Dom( EclipseWtpApplicationXMLWriter.MODULEMAP_EARPROJECT_MAP );
289         result.setAttribute( EclipseWtpApplicationXMLWriter.XMI_VERSION, "2.0" );
290         result.setAttribute( EclipseWtpApplicationXMLWriter.XMLNS_XMI, "http://www.omg.org/XMI" );
291         result.setAttribute( EclipseWtpApplicationXMLWriter.XMLNS_APPLICATION, "application.xmi" );
292         result.setAttribute( EclipseWtpApplicationXMLWriter.XMLNS_MODULEMAP, "modulemap.xmi" );
293         result.setAttribute( EclipseWtpApplicationXMLWriter.XMI_ID, "EARProjectMap_" + System.identityHashCode( this ) );
294         return result;
295     }
296 
297     /**
298      * find an existing module entry in the application.xml file by looking up the id in the modulemaps file and then
299      * using that to locate the entry in the application.xml file.
300      * 
301      * @param applicationXmlDom application.xml dom tree
302      * @param mapping .modulemaps dom tree
303      * @return dom tree representing the module
304      */
305     private Xpp3Dom findModuleInApplicationXml( Xpp3Dom applicationXmlDom, Xpp3Dom mapping )
306     {
307         String id = getIdFromMapping( mapping );
308         Xpp3Dom[] children = applicationXmlDom.getChildren();
309         for (Xpp3Dom aChildren : children) {
310             String childId = aChildren.getAttribute(EclipseWtpApplicationXMLWriter.ID);
311             if (childId != null && childId.equals(id)) {
312                 return aChildren;
313             }
314         }
315         return null;
316     }
317 
318     /**
319      * find an artifact in the modulemaps dom tree, if it is missing create a new entry in the modulemaps dom tree.
320      * 
321      * @param dependency dependency to find
322      * @param modulemapXmlDom dom-tree of modulemaps
323      * @return dom-tree representing the artifact
324      */
325     private Xpp3Dom findOrCreateArtifact( IdeDependency dependency, Xpp3Dom modulemapXmlDom )
326     {
327         // first try to find it
328         Xpp3Dom[] children = modulemapXmlDom.getChildren();
329         for ( int index = 0; index < children.length; index++ )
330         {
331             if ( children[index].getAttribute( EclipseWtpApplicationXMLWriter.MODULEMAPS_PROJECT_NAME ).equals(
332                                                                                                                 dependency.getEclipseProjectName() ) )
333             {
334                 if ( ( dependency.getType().equals( Constants.PROJECT_PACKAGING_EJB ) || dependency.getType().equals(
335                                                                                                                       "ejb3" ) )
336                     && children[index].getName().equals( EclipseWtpApplicationXMLWriter.MODULEMAPS_MAPPINGS )
337                     && children[index].getChild( EclipseWtpApplicationXMLWriter.APPLICATION_XML_MODULE ).getAttribute(
338                                                                                                                        EclipseWtpApplicationXMLWriter.XMI_TYPE ).equals(
339                                                                                                                                                                          EclipseWtpApplicationXMLWriter.MODULEMAPS_APPLICATION_EJB_MODULE ) )
340                 {
341                     return children[index];
342                 }
343                 else if ( dependency.getType().equals( Constants.PROJECT_PACKAGING_WAR )
344                     && children[index].getName().equals( EclipseWtpApplicationXMLWriter.MODULEMAPS_MAPPINGS )
345                     && children[index].getChild( EclipseWtpApplicationXMLWriter.APPLICATION_XML_MODULE ).getAttribute(
346                                                                                                                        EclipseWtpApplicationXMLWriter.XMI_TYPE ).equals(
347                                                                                                                                                                          EclipseWtpApplicationXMLWriter.MODULEMAPS_APPLICATION_WEB_MODULE ) )
348                 {
349                     return children[index];
350                 }
351                 else if ( dependency.getType().equals( Constants.PROJECT_PACKAGING_JAR )
352                     && children[index].getName().equals( EclipseWtpApplicationXMLWriter.MODULEMAPS_UTILITY_JARMAPPINGS ) )
353                 {
354                     return children[index];
355                 }
356                 else
357                 {
358                     modulemapXmlDom.removeChild( index );
359                     break;
360                 }
361             }
362         }
363         // ok, its missing (or it changed type). create a new one based on its
364         // type
365         long id = System.identityHashCode( dependency );
366         if ( dependency.getType().equals( Constants.PROJECT_PACKAGING_EJB ) || dependency.getType().equals( "ejb3" ) )
367         {
368             Xpp3Dom mapping = new Xpp3Dom( EclipseWtpApplicationXMLWriter.MODULEMAPS_MAPPINGS );
369             mapping.setAttribute( EclipseWtpApplicationXMLWriter.XMI_ID, "ModuleMapping_" + id );
370             mapping.setAttribute( EclipseWtpApplicationXMLWriter.MODULEMAPS_PROJECT_NAME,
371                                   dependency.getEclipseProjectName() );
372             Xpp3Dom module = new Xpp3Dom( EclipseWtpApplicationXMLWriter.APPLICATION_XML_MODULE );
373             module.setAttribute( EclipseWtpApplicationXMLWriter.XMI_TYPE,
374                                  EclipseWtpApplicationXMLWriter.MODULEMAPS_APPLICATION_EJB_MODULE );
375             module.setAttribute( EclipseWtpApplicationXMLWriter.HREF, "META-INF/application.xml#EjbModule_" + id );
376             mapping.addChild( module );
377             modulemapXmlDom.addChild( mapping );
378             return mapping;
379         }
380         else if ( dependency.getType().equals( Constants.PROJECT_PACKAGING_WAR ) )
381         {
382             Xpp3Dom mapping = new Xpp3Dom( EclipseWtpApplicationXMLWriter.MODULEMAPS_MAPPINGS );
383             mapping.setAttribute( EclipseWtpApplicationXMLWriter.XMI_ID, "ModuleMapping_" + id );
384             mapping.setAttribute( EclipseWtpApplicationXMLWriter.MODULEMAPS_PROJECT_NAME,
385                                   dependency.getEclipseProjectName() );
386             Xpp3Dom module = new Xpp3Dom( EclipseWtpApplicationXMLWriter.APPLICATION_XML_MODULE );
387             module.setAttribute( EclipseWtpApplicationXMLWriter.XMI_TYPE,
388                                  EclipseWtpApplicationXMLWriter.MODULEMAPS_APPLICATION_WEB_MODULE );
389             module.setAttribute( EclipseWtpApplicationXMLWriter.HREF, "META-INF/application.xml#WebModule_" + id );
390             mapping.addChild( module );
391             modulemapXmlDom.addChild( mapping );
392             return mapping;
393         }
394         else
395         {
396             Xpp3Dom utilityJARMapping = new Xpp3Dom( EclipseWtpApplicationXMLWriter.MODULEMAPS_UTILITY_JARMAPPINGS );
397             utilityJARMapping.setAttribute( EclipseWtpApplicationXMLWriter.XMI_ID, "UtilityJARMapping_" + id );
398             utilityJARMapping.setAttribute( EclipseWtpApplicationXMLWriter.MODULEMAPS_PROJECT_NAME,
399                                             dependency.getEclipseProjectName() );
400             utilityJARMapping.setAttribute( EclipseWtpApplicationXMLWriter.URI, dependency.getEclipseProjectName()
401                 + ".jar" );
402             modulemapXmlDom.addChild( utilityJARMapping );
403             return utilityJARMapping;
404         }
405     }
406 
407     /**
408      * get the id from the href of a modulemap.
409      * 
410      * @param mapping the dom-tree of modulemaps
411      * @return module identifier
412      */
413     private String getIdFromMapping( Xpp3Dom mapping )
414     {
415         if ( mapping.getChildCount() < 1 )
416         {
417             return "";
418         }
419         String href = mapping.getChild( 0 ).getAttribute( EclipseWtpApplicationXMLWriter.HREF );
420         String id = href.substring( href.indexOf( '#' ) + 1 );
421         return id;
422     }
423 
424     /**
425      * read an xml file (application.xml or .modulemaps).
426      * 
427      * @param xmlFile an xmlfile
428      * @return dom-tree representing the file contents
429      */
430     private Xpp3Dom readXMLFile( File xmlFile )
431     {
432         try
433         {
434             Reader reader = new InputStreamReader( new FileInputStream( xmlFile ), "UTF-8" );
435             Xpp3Dom applicationXmlDom = Xpp3DomBuilder.build( reader );
436             return applicationXmlDom;
437         }
438         catch ( FileNotFoundException e )
439         {
440             return null;
441         }
442         catch ( Exception e )
443         {
444             this.log.error( "cantreadfile" + xmlFile.getAbsolutePath() );
445             // this will trigger creating a new file
446             return null;
447         }
448     }
449 
450     /**
451      * mark the domtree entry as handled (all not handled ones will be deleted).
452      * 
453      * @param xpp3Dom dom element to mark handled
454      */
455     private void handled( Xpp3Dom xpp3Dom )
456     {
457         for ( int index = 0; index < this.applicationXmlDomChildren.length; index++ )
458         {
459             if ( this.applicationXmlDomChildren[index] == xpp3Dom )
460             {
461                 this.applicationXmlDomChildren[index] = null;
462             }
463         }
464         for ( int index = 0; index < this.modulemapsXmlDomChildren.length; index++ )
465         {
466             if ( this.modulemapsXmlDomChildren[index] == xpp3Dom )
467             {
468                 this.modulemapsXmlDomChildren[index] = null;
469             }
470         }
471     }
472 
473     /**
474      * delete all unused entries from the dom-trees.
475      * 
476      * @param applicationXmlDom dom-tree of application.xml
477      * @param modulemapsXmlDom dom-tree of modulemaps
478      */
479     private void removeUnusedEntries( Xpp3Dom applicationXmlDom, Xpp3Dom modulemapsXmlDom )
480     {
481         for (Xpp3Dom aModulemapsXmlDomChildren : this.modulemapsXmlDomChildren) {
482             if (aModulemapsXmlDomChildren != null) {
483                 Xpp3Dom[] newModulemapsXmlDomChildren = modulemapsXmlDom.getChildren();
484                 for (int newIndex = 0; newIndex < newModulemapsXmlDomChildren.length; newIndex++) {
485                     if (newModulemapsXmlDomChildren[newIndex] == aModulemapsXmlDomChildren) {
486                         modulemapsXmlDom.removeChild(newIndex);
487                         break;
488                     }
489                 }
490             }
491         }
492         for (Xpp3Dom anApplicationXmlDomChildren : this.applicationXmlDomChildren) {
493             if (anApplicationXmlDomChildren != null) {
494                 Xpp3Dom[] newApplicationXmlDomChildren = applicationXmlDom.getChildren();
495                 for (int newIndex = 0; newIndex < newApplicationXmlDomChildren.length; newIndex++) {
496                     if (newApplicationXmlDomChildren[newIndex] == anApplicationXmlDomChildren) {
497                         applicationXmlDom.removeChild(newIndex);
498                         break;
499                     }
500                 }
501             }
502         }
503     }
504 
505     /**
506      * update the application.xml and the .modulemaps file for a specified dependency.all WAR an EJB dependencies will
507      * go in both files all others only in the modulemaps files. Webapplications contextroots are corrected to the
508      * contextRoot specified in the pom.
509      * 
510      * @param applicationXmlDom dom-tree of application.xml
511      * @param modulemapXmlDom dom-tree of modulemaps
512      * @param dependency the eclipse dependency to handle
513      */
514     private void updateApplicationXml( Xpp3Dom applicationXmlDom, Xpp3Dom modulemapXmlDom, IdeDependency dependency )
515     {
516         if ( dependency.isTestDependency() || dependency.isProvided()
517             || dependency.isSystemScopedOutsideProject( this.config.getProject() ) )
518         {
519             return;
520         }
521         Xpp3Dom mapping = findOrCreateArtifact( dependency, modulemapXmlDom );
522         handled( mapping );
523         if ( dependency.getType().equals( Constants.PROJECT_PACKAGING_EJB ) || dependency.getType().equals( "ejb3" ) )
524         {
525             Xpp3Dom module = findModuleInApplicationXml( applicationXmlDom, mapping );
526             if ( module == null )
527             {
528                 module = new Xpp3Dom( EclipseWtpApplicationXMLWriter.APPLICATION_XML_MODULE );
529                 module.setAttribute( EclipseWtpApplicationXMLWriter.ID, getIdFromMapping( mapping ) );
530                 Xpp3Dom ejb = new Xpp3Dom( "ejb" );
531                 ejb.setValue( dependency.getEclipseProjectName() + ".jar" );
532                 module.addChild( ejb );
533                 applicationXmlDom.addChild( module );
534             }
535             else
536             {
537                 handled( module );
538                 module.getChild( "ejb" ).setValue( dependency.getEclipseProjectName() + ".jar" );
539             }
540         }
541         else if ( dependency.getType().equals( Constants.PROJECT_PACKAGING_WAR ) )
542         {
543             String contextRootInPom = getContextRootFor( dependency );
544             Xpp3Dom module = findModuleInApplicationXml( applicationXmlDom, mapping );
545             if ( module == null )
546             {
547                 module = new Xpp3Dom( EclipseWtpApplicationXMLWriter.APPLICATION_XML_MODULE );
548                 module.setAttribute( EclipseWtpApplicationXMLWriter.ID, getIdFromMapping( mapping ) );
549                 Xpp3Dom web = new Xpp3Dom( EclipseWtpApplicationXMLWriter.APPLICATION_XML_WEB );
550                 Xpp3Dom webUri = new Xpp3Dom( EclipseWtpApplicationXMLWriter.APPLICATION_XML_WEB_URI );
551                 webUri.setValue( dependency.getEclipseProjectName() + ".war" );
552                 Xpp3Dom contextRoot = new Xpp3Dom( EclipseWtpApplicationXMLWriter.APPLICATION_XML_CONTEXT_ROOT );
553                 contextRoot.setValue( contextRootInPom );
554                 web.addChild( webUri );
555                 web.addChild( contextRoot );
556                 module.addChild( web );
557                 applicationXmlDom.addChild( module );
558             }
559             else
560             {
561                 handled( module );
562                 module.getChild( EclipseWtpApplicationXMLWriter.APPLICATION_XML_WEB ).getChild(
563                                                                                                 EclipseWtpApplicationXMLWriter.APPLICATION_XML_WEB_URI ).setValue(
564                                                                                                                                                                    dependency.getEclipseProjectName()
565                                                                                                                                                                        + ".war" );
566                 module.getChild( EclipseWtpApplicationXMLWriter.APPLICATION_XML_WEB ).getChild(
567                                                                                                 EclipseWtpApplicationXMLWriter.APPLICATION_XML_CONTEXT_ROOT ).setValue(
568                                                                                                                                                                         contextRootInPom );
569             }
570         }
571     }
572 
573     /**
574      * Find the contextRoot specified in the pom and convert it into contectroot for the application.xml.
575      * 
576      * @param dependency the artifact to search
577      * @return string with the context root
578      */
579     private String getContextRootFor( IdeDependency dependency )
580     {
581         String artifactId = dependency.getArtifactId();
582         String groupId = dependency.getGroupId();
583         for (Xpp3Dom webModulesFromPom : this.webModulesFromPoms) {
584             Xpp3Dom webGroupId = webModulesFromPom.getChild("groupId");
585             Xpp3Dom webArtifactId = webModulesFromPom.getChild("artifactId");
586             Xpp3Dom webContextRoot = webModulesFromPom.getChild("contextRoot");
587 
588             if (webContextRoot != null && webArtifactId != null && webArtifactId.getValue().equals(artifactId)
589                     && webGroupId != null && webGroupId.getValue().equals(groupId)) {
590                 return webContextRoot.getValue();
591             }
592         }
593         // no configuration found back to maven-ear-plugin default
594         return dependency.getArtifactId();
595     }
596 
597     /**
598      * write back a domtree to a xmlfile and use the pretty print for it so that it is human readable.
599      * 
600      * @param xmlFile file to write to
601      * @param xmlDomTree dom-tree to write
602      * @throws MojoExecutionException if the file could not be written
603      */
604     private void writePrettyXmlFile( File xmlFile, Xpp3Dom xmlDomTree )
605         throws MojoExecutionException
606     {
607         Xpp3Dom original = readXMLFile( xmlFile );
608         if ( original != null && original.equals( xmlDomTree ) )
609         {
610             this.log.info( "Rad6CleanMojo.unchanged" + xmlFile.getAbsolutePath() );
611             return;
612         }
613         Writer w;
614         xmlFile.getParentFile().mkdirs();
615         try
616         {
617             w = new OutputStreamWriter( new FileOutputStream( xmlFile ), "UTF-8" );
618         }
619         catch ( IOException ex )
620         {
621             throw new MojoExecutionException( "Rad6Plugin.erroropeningfile", ex ); //$NON-NLS-1$
622         }
623         XMLWriter writer = new PrettyPrintXMLWriter( w, "UTF-8", null );
624         Xpp3DomWriter.write( writer, xmlDomTree );
625         IOUtil.close( w );
626     }
627 
628 }