1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  package org.apache.maven.plugin.eclipse.writers.rad;
20  
21  import java.io.File;
22  import java.io.FileInputStream;
23  import java.io.FileNotFoundException;
24  import java.io.FileOutputStream;
25  import java.io.IOException;
26  import java.io.InputStreamReader;
27  import java.io.OutputStreamWriter;
28  import java.io.Reader;
29  import java.io.Writer;
30  
31  import org.apache.maven.artifact.repository.ArtifactRepository;
32  import org.apache.maven.plugin.MojoExecutionException;
33  import org.apache.maven.plugin.eclipse.Constants;
34  import org.apache.maven.plugin.eclipse.EclipseSourceDir;
35  import org.apache.maven.plugin.eclipse.Messages;
36  import org.apache.maven.plugin.eclipse.writers.AbstractEclipseWriter;
37  import org.apache.maven.plugin.eclipse.writers.wtp.AbstractWtpResourceWriter;
38  import org.apache.maven.plugin.ide.IdeDependency;
39  import org.apache.maven.plugin.ide.IdeUtils;
40  import org.apache.maven.plugin.ide.JeeUtils;
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  
50  
51  
52  
53  
54  
55  public class RadApplicationXMLWriter
56      extends AbstractEclipseWriter
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 = "xsi:schemaLocation";
110 
111     private static final String XMLNS_XMI = "xmlns:xmi";
112 
113     private static final String XMLNS_XSI = "xmlns:xsi";
114 
115     private Xpp3Dom[] applicationXmlDomChildren;
116 
117     private long baseId = System.currentTimeMillis();
118 
119     private Xpp3Dom[] modulemapsXmlDomChildren;
120 
121     private Xpp3Dom[] webModulesFromPoms;
122 
123     
124 
125 
126 
127 
128 
129 
130 
131 
132     public void write()
133         throws MojoExecutionException
134     {
135         String packaging = config.getPackaging();
136         if ( Constants.PROJECT_PACKAGING_EAR.equalsIgnoreCase( packaging ) )
137         {
138             File applicationXmlFile =
139                 new File( config.getEclipseProjectDirectory(), "META-INF" + File.separator + APPLICATION_XML_FILENAME );
140             Xpp3Dom applicationXmlDom = readXMLFile( applicationXmlFile );
141             if ( applicationXmlDom == null )
142             {
143                 applicationXmlDom = createNewApplicationXml();
144             }
145             this.applicationXmlDomChildren = applicationXmlDom.getChildren( APPLICATION_XML_MODULE );
146 
147             File modulemapsXmlFile =
148                 new File( config.getEclipseProjectDirectory(), "META-INF" + File.separator + MODULEMAPS_FILENAME );
149             Xpp3Dom modulemapsXmlDom = readXMLFile( modulemapsXmlFile );
150             if ( modulemapsXmlDom == null )
151             {
152                 modulemapsXmlDom = createNewModulemaps();
153             }
154             this.modulemapsXmlDomChildren = modulemapsXmlDom.getChildren();
155 
156             this.webModulesFromPoms =
157                 IdeUtils.getPluginConfigurationDom( config.getProject(), JeeUtils.ARTIFACT_MAVEN_EAR_PLUGIN,
158                                                     new String[] { "modules", "webModule" } );
159 
160             IdeDependency[] deps = config.getDeps();
161             for (IdeDependency dep : deps) {
162                 updateApplicationXml(applicationXmlDom, modulemapsXmlDom, dep);
163             }
164 
165             removeUnusedEntries( applicationXmlDom, modulemapsXmlDom );
166 
167             writePrettyXmlFile( applicationXmlFile, applicationXmlDom );
168             writePrettyXmlFile( modulemapsXmlFile, modulemapsXmlDom );
169         }
170     }
171 
172     
173 
174 
175 
176 
177     private Xpp3Dom createNewApplicationXml()
178     {
179         String jeeVersion;
180         if ( config.getJeeVersion() != null )
181         {
182             jeeVersion = JeeUtils.getJeeDescriptorFromJeeVersion( config.getJeeVersion() ).getJeeVersion();
183         }
184         else
185         {
186             jeeVersion = JeeUtils.resolveJeeVersion( config.getProject() );
187         }
188         
189         
190         Xpp3Dom result = new Xpp3Dom( APPLICATION_XML_APPLICATION );
191         result.setAttribute( ID, "Application_ID" );
192         result.setAttribute( VERSION, jeeVersion );
193         result.setAttribute( XMLNS, "http://java.sun.com/xml/ns/j2ee" );
194         result.setAttribute( XMLNS_XSI, "http://www.w3.org/2001/XMLSchema-instance" );
195         result.setAttribute( XMLNS_SCHEMA_LOCATION,
196                              "http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/application_"
197                                  + jeeVersion.charAt( 0 ) + "_" + jeeVersion.charAt( 2 ) + ".xsd" );
198         result.addChild( new Xpp3Dom( APPLICATION_XML_DESCRIPTION ) );
199         Xpp3Dom name = new Xpp3Dom( APPLICATION_XML_DISPLAY_NAME );
200         name.setValue( config.getProject().getArtifactId() );
201         result.addChild( name );
202         return result;
203     }
204 
205     
206 
207 
208 
209 
210     private Xpp3Dom createNewModulemaps()
211     {
212         Xpp3Dom result = new Xpp3Dom( MODULEMAP_EARPROJECT_MAP );
213         result.setAttribute( XMI_VERSION, "2.0" );
214         result.setAttribute( XMLNS_XMI, "http://www.omg.org/XMI" );
215         result.setAttribute( XMLNS_APPLICATION, "application.xmi" );
216         result.setAttribute( XMLNS_MODULEMAP, "modulemap.xmi" );
217         result.setAttribute( XMI_ID, "EARProjectMap_" + ( this.baseId++ ) );
218         return result;
219     }
220 
221     
222 
223 
224 
225 
226 
227 
228 
229     private Xpp3Dom findModuleInApplicationXml( Xpp3Dom applicationXmlDom, Xpp3Dom mapping )
230     {
231         String id = getIdFromMapping( mapping );
232         Xpp3Dom[] children = applicationXmlDom.getChildren();
233         for (Xpp3Dom aChildren : children) {
234             String childId = aChildren.getAttribute(ID);
235             if (childId != null && childId.equals(id)) {
236                 return aChildren;
237             }
238         }
239         return null;
240     }
241 
242     
243 
244 
245 
246 
247 
248 
249     private Xpp3Dom findOrCreateArtifact( IdeDependency dependency, Xpp3Dom modulemapXmlDom )
250     {
251         
252         Xpp3Dom[] children = modulemapXmlDom.getChildren();
253         for ( int index = 0; index < children.length; index++ )
254         {
255             if ( children[index].getAttribute( MODULEMAPS_PROJECT_NAME ).equals( dependency.getArtifactId() ) )
256             {
257                 if ( dependency.getType().equals( Constants.PROJECT_PACKAGING_EJB )
258                     && children[index].getName().equals( MODULEMAPS_MAPPINGS )
259                     && children[index].getChild( APPLICATION_XML_MODULE ).getAttribute( XMI_TYPE ).equals(
260                                                                                                            MODULEMAPS_APPLICATION_EJB_MODULE ) )
261                 {
262                     return children[index];
263                 }
264                 else if ( dependency.getType().equals( Constants.PROJECT_PACKAGING_WAR )
265                     && children[index].getName().equals( MODULEMAPS_MAPPINGS )
266                     && children[index].getChild( APPLICATION_XML_MODULE ).getAttribute( XMI_TYPE ).equals(
267                                                                                                            MODULEMAPS_APPLICATION_WEB_MODULE ) )
268                 {
269                     return children[index];
270                 }
271                 else if ( dependency.getType().equals( Constants.PROJECT_PACKAGING_JAR )
272                     && children[index].getName().equals( MODULEMAPS_UTILITY_JARMAPPINGS ) )
273                 {
274                     return children[index];
275                 }
276                 else
277                 {
278                     modulemapXmlDom.removeChild( index );
279                     break;
280                 }
281             }
282         }
283         
284         
285         long id = this.baseId++;
286         if ( dependency.getType().equals( Constants.PROJECT_PACKAGING_EJB ) )
287         {
288             Xpp3Dom mapping = new Xpp3Dom( MODULEMAPS_MAPPINGS );
289             mapping.setAttribute( XMI_ID, "ModuleMapping_" + id );
290             mapping.setAttribute( MODULEMAPS_PROJECT_NAME, dependency.getArtifactId() );
291             Xpp3Dom module = new Xpp3Dom( APPLICATION_XML_MODULE );
292             module.setAttribute( XMI_TYPE, MODULEMAPS_APPLICATION_EJB_MODULE );
293             module.setAttribute( HREF, "META-INF/application.xml#EjbModule_" + id );
294             mapping.addChild( module );
295             modulemapXmlDom.addChild( mapping );
296             return mapping;
297         }
298         else if ( dependency.getType().equals( Constants.PROJECT_PACKAGING_WAR ) )
299         {
300             Xpp3Dom mapping = new Xpp3Dom( MODULEMAPS_MAPPINGS );
301             mapping.setAttribute( XMI_ID, "ModuleMapping_" + id );
302             mapping.setAttribute( MODULEMAPS_PROJECT_NAME, dependency.getArtifactId() );
303             Xpp3Dom module = new Xpp3Dom( APPLICATION_XML_MODULE );
304             module.setAttribute( XMI_TYPE, MODULEMAPS_APPLICATION_WEB_MODULE );
305             module.setAttribute( HREF, "META-INF/application.xml#WebModule_" + id );
306             mapping.addChild( module );
307             modulemapXmlDom.addChild( mapping );
308             return mapping;
309         }
310         else
311         {
312             Xpp3Dom utilityJARMapping = new Xpp3Dom( MODULEMAPS_UTILITY_JARMAPPINGS );
313             utilityJARMapping.setAttribute( XMI_ID, "UtilityJARMapping_" + id );
314             utilityJARMapping.setAttribute( MODULEMAPS_PROJECT_NAME, dependency.getArtifactId() );
315             utilityJARMapping.setAttribute( URI, dependency.getArtifactId() + ".jar" );
316             modulemapXmlDom.addChild( utilityJARMapping );
317             return utilityJARMapping;
318         }
319     }
320 
321     
322 
323 
324 
325 
326 
327     private String getIdFromMapping( Xpp3Dom mapping )
328     {
329         if ( mapping.getChildCount() < 1 )
330         {
331             return "";
332         }
333         String href = mapping.getChild( 0 ).getAttribute( HREF );
334         String id = href.substring( href.indexOf( '#' ) + 1 );
335         return id;
336     }
337 
338     
339 
340 
341 
342 
343     private void handled( Xpp3Dom xpp3Dom )
344     {
345         for ( int index = 0; index < this.applicationXmlDomChildren.length; index++ )
346         {
347             if ( this.applicationXmlDomChildren[index] == xpp3Dom )
348             {
349                 this.applicationXmlDomChildren[index] = null;
350             }
351         }
352         for ( int index = 0; index < this.modulemapsXmlDomChildren.length; index++ )
353         {
354             if ( this.modulemapsXmlDomChildren[index] == xpp3Dom )
355             {
356                 this.modulemapsXmlDomChildren[index] = null;
357             }
358         }
359     }
360 
361     
362 
363 
364 
365 
366 
367     private Xpp3Dom readXMLFile( File xmlFile )
368     {
369         try
370         {
371             Reader reader = new InputStreamReader( new FileInputStream( xmlFile ), "UTF-8" );
372             Xpp3Dom applicationXmlDom = Xpp3DomBuilder.build( reader );
373             return applicationXmlDom;
374         }
375         catch ( FileNotFoundException e )
376         {
377             return null;
378         }
379         catch ( Exception e )
380         {
381             log.error( Messages.getString( "EclipsePlugin.cantreadfile", xmlFile.getAbsolutePath() ) );
382             
383             return null;
384         }
385     }
386 
387     
388 
389 
390 
391 
392 
393     private void removeUnusedEntries( Xpp3Dom applicationXmlDom, Xpp3Dom modulemapsXmlDom )
394     {
395         for (Xpp3Dom aModulemapsXmlDomChildren : this.modulemapsXmlDomChildren) {
396             if (aModulemapsXmlDomChildren != null) {
397                 Xpp3Dom[] newModulemapsXmlDomChildren = modulemapsXmlDom.getChildren();
398                 for (int newIndex = 0; newIndex < newModulemapsXmlDomChildren.length; newIndex++) {
399                     if ((newModulemapsXmlDomChildren[newIndex] != null)
400                             && (newModulemapsXmlDomChildren[newIndex] == aModulemapsXmlDomChildren)) {
401                         modulemapsXmlDom.removeChild(newIndex);
402                         break;
403                     }
404                 }
405             }
406         }
407         for (Xpp3Dom anApplicationXmlDomChildren : this.applicationXmlDomChildren) {
408             if (anApplicationXmlDomChildren != null) {
409                 Xpp3Dom[] newApplicationXmlDomChildren = applicationXmlDom.getChildren();
410                 for (int newIndex = 0; newIndex < newApplicationXmlDomChildren.length; newIndex++) {
411                     if (newApplicationXmlDomChildren[newIndex] == anApplicationXmlDomChildren) {
412                         applicationXmlDom.removeChild(newIndex);
413                         break;
414                     }
415                 }
416             }
417         }
418     }
419 
420     
421 
422 
423 
424 
425 
426 
427 
428 
429     private void updateApplicationXml( Xpp3Dom applicationXmlDom, Xpp3Dom modulemapXmlDom, IdeDependency dependency )
430     {
431         boolean isEar = Constants.PROJECT_PACKAGING_EJB.equals( dependency.getType() );
432         boolean isWar = Constants.PROJECT_PACKAGING_WAR.equals( dependency.getType() );
433 
434         if ( dependency.isReferencedProject() || isEar || isWar )
435         {
436             Xpp3Dom mapping = findOrCreateArtifact( dependency, modulemapXmlDom );
437             handled( mapping );
438             if ( isEar )
439             {
440                 Xpp3Dom module = findModuleInApplicationXml( applicationXmlDom, mapping );
441                 if ( module == null )
442                 {
443                     module = new Xpp3Dom( APPLICATION_XML_MODULE );
444                     module.setAttribute( ID, getIdFromMapping( mapping ) );
445                     Xpp3Dom ejb = new Xpp3Dom( Constants.PROJECT_PACKAGING_EJB );
446                     ejb.setValue( dependency.getArtifactId() + ".jar" );
447                     module.addChild( ejb );
448                     applicationXmlDom.addChild( module );
449                 }
450                 else
451                 {
452                     handled( module );
453                     module.getChild( Constants.PROJECT_PACKAGING_EJB ).setValue( dependency.getArtifactId() + ".jar" );
454                 }
455             }
456             else if ( isWar )
457             {
458                 String contextRootInPom = getContextRootFor( dependency.getArtifactId() );
459                 Xpp3Dom module = findModuleInApplicationXml( applicationXmlDom, mapping );
460                 if ( module == null )
461                 {
462                     module = new Xpp3Dom( APPLICATION_XML_MODULE );
463                     module.setAttribute( ID, getIdFromMapping( mapping ) );
464                     Xpp3Dom web = new Xpp3Dom( APPLICATION_XML_WEB );
465                     Xpp3Dom webUri = new Xpp3Dom( APPLICATION_XML_WEB_URI );
466                     webUri.setValue( dependency.getArtifactId() + ".war" );
467                     Xpp3Dom contextRoot = new Xpp3Dom( APPLICATION_XML_CONTEXT_ROOT );
468                     contextRoot.setValue( contextRootInPom );
469                     web.addChild( webUri );
470                     web.addChild( contextRoot );
471                     module.addChild( web );
472                     applicationXmlDom.addChild( module );
473                 }
474                 else
475                 {
476                     handled( module );
477                     module.getChild( APPLICATION_XML_WEB ).getChild( APPLICATION_XML_WEB_URI ).setValue(
478                                                                                                          dependency.getArtifactId()
479                                                                                                              + ".war" );
480                     module.getChild( APPLICATION_XML_WEB ).getChild( APPLICATION_XML_CONTEXT_ROOT ).setValue(
481                                                                                                               contextRootInPom );
482                 }
483             }
484         }
485     }
486 
487     
488 
489 
490 
491 
492 
493     private String getContextRootFor( String artifactId )
494     {
495         for (Xpp3Dom webModulesFromPom : webModulesFromPoms) {
496             if (webModulesFromPom.getChild("artifactId").getValue().equals(artifactId))
497                 return new File(webModulesFromPom.getChild("contextRoot").getValue()).getName();
498         }
499         return artifactId;
500     }
501 
502     
503 
504 
505 
506 
507 
508 
509     private void writePrettyXmlFile( File xmlFile, Xpp3Dom xmlDomTree )
510         throws MojoExecutionException
511     {
512         Xpp3Dom original = readXMLFile( xmlFile );
513         if ( original != null && original.equals( xmlDomTree ) )
514         {
515             log.info( Messages.getString( "EclipsePlugin.unchangedmanifest", xmlFile.getAbsolutePath() ) );
516             return;
517         }
518         Writer w;
519         xmlFile.getParentFile().mkdirs();
520         try
521         {
522             w = new OutputStreamWriter( new FileOutputStream( xmlFile ), "UTF-8" );
523         }
524         catch ( IOException ex )
525         {
526             throw new MojoExecutionException( Messages.getString( "EclipsePlugin.erroropeningfile" ), ex ); 
527         }
528         XMLWriter writer = new PrettyPrintXMLWriter( w, "UTF-8", null );
529         Xpp3DomWriter.write( writer, xmlDomTree );
530         IOUtil.close( w );
531     }
532 }