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 ( int index = 0; index < deps.length; index++ )
162 {
163 updateApplicationXml( applicationXmlDom, modulemapsXmlDom, deps[index] );
164 }
165
166 removeUnusedEntries( applicationXmlDom, modulemapsXmlDom );
167
168 writePrettyXmlFile( applicationXmlFile, applicationXmlDom );
169 writePrettyXmlFile( modulemapsXmlFile, modulemapsXmlDom );
170 }
171 }
172
173
174
175
176
177
178 private Xpp3Dom createNewApplicationXml()
179 {
180 String jeeVersion;
181 if ( config.getJeeVersion() != null )
182 {
183 jeeVersion = JeeUtils.getJeeDescriptorFromJeeVersion( config.getJeeVersion() ).getJeeVersion();
184 }
185 else
186 {
187 jeeVersion = JeeUtils.resolveJeeVersion( config.getProject() );
188 }
189
190
191 Xpp3Dom result = new Xpp3Dom( APPLICATION_XML_APPLICATION );
192 result.setAttribute( ID, "Application_ID" );
193 result.setAttribute( VERSION, jeeVersion );
194 result.setAttribute( XMLNS, "http://java.sun.com/xml/ns/j2ee" );
195 result.setAttribute( XMLNS_XSI, "http://www.w3.org/2001/XMLSchema-instance" );
196 result.setAttribute( XMLNS_SCHEMA_LOCATION,
197 "http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/application_"
198 + jeeVersion.charAt( 0 ) + "_" + jeeVersion.charAt( 2 ) + ".xsd" );
199 result.addChild( new Xpp3Dom( APPLICATION_XML_DESCRIPTION ) );
200 Xpp3Dom name = new Xpp3Dom( APPLICATION_XML_DISPLAY_NAME );
201 name.setValue( config.getProject().getArtifactId() );
202 result.addChild( name );
203 return result;
204 }
205
206
207
208
209
210
211 private Xpp3Dom createNewModulemaps()
212 {
213 Xpp3Dom result = new Xpp3Dom( MODULEMAP_EARPROJECT_MAP );
214 result.setAttribute( XMI_VERSION, "2.0" );
215 result.setAttribute( XMLNS_XMI, "http://www.omg.org/XMI" );
216 result.setAttribute( XMLNS_APPLICATION, "application.xmi" );
217 result.setAttribute( XMLNS_MODULEMAP, "modulemap.xmi" );
218 result.setAttribute( XMI_ID, "EARProjectMap_" + ( this.baseId++ ) );
219 return result;
220 }
221
222
223
224
225
226
227
228
229
230 private Xpp3Dom findModuleInApplicationXml( Xpp3Dom applicationXmlDom, Xpp3Dom mapping )
231 {
232 String id = getIdFromMapping( mapping );
233 Xpp3Dom[] children = applicationXmlDom.getChildren();
234 for ( int index = 0; index < children.length; index++ )
235 {
236 String childId = children[index].getAttribute( ID );
237 if ( childId != null && childId.equals( id ) )
238 {
239 return children[index];
240 }
241 }
242 return null;
243 }
244
245
246
247
248
249
250
251
252 private Xpp3Dom findOrCreateArtifact( IdeDependency dependency, Xpp3Dom modulemapXmlDom )
253 {
254
255 Xpp3Dom[] children = modulemapXmlDom.getChildren();
256 for ( int index = 0; index < children.length; index++ )
257 {
258 if ( children[index].getAttribute( MODULEMAPS_PROJECT_NAME ).equals( dependency.getArtifactId() ) )
259 {
260 if ( dependency.getType().equals( Constants.PROJECT_PACKAGING_EJB )
261 && children[index].getName().equals( MODULEMAPS_MAPPINGS )
262 && children[index].getChild( APPLICATION_XML_MODULE ).getAttribute( XMI_TYPE ).equals(
263 MODULEMAPS_APPLICATION_EJB_MODULE ) )
264 {
265 return children[index];
266 }
267 else if ( dependency.getType().equals( Constants.PROJECT_PACKAGING_WAR )
268 && children[index].getName().equals( MODULEMAPS_MAPPINGS )
269 && children[index].getChild( APPLICATION_XML_MODULE ).getAttribute( XMI_TYPE ).equals(
270 MODULEMAPS_APPLICATION_WEB_MODULE ) )
271 {
272 return children[index];
273 }
274 else if ( dependency.getType().equals( Constants.PROJECT_PACKAGING_JAR )
275 && children[index].getName().equals( MODULEMAPS_UTILITY_JARMAPPINGS ) )
276 {
277 return children[index];
278 }
279 else
280 {
281 modulemapXmlDom.removeChild( index );
282 break;
283 }
284 }
285 }
286
287
288 long id = this.baseId++;
289 if ( dependency.getType().equals( Constants.PROJECT_PACKAGING_EJB ) )
290 {
291 Xpp3Dom mapping = new Xpp3Dom( MODULEMAPS_MAPPINGS );
292 mapping.setAttribute( XMI_ID, "ModuleMapping_" + id );
293 mapping.setAttribute( MODULEMAPS_PROJECT_NAME, dependency.getArtifactId() );
294 Xpp3Dom module = new Xpp3Dom( APPLICATION_XML_MODULE );
295 module.setAttribute( XMI_TYPE, MODULEMAPS_APPLICATION_EJB_MODULE );
296 module.setAttribute( HREF, "META-INF/application.xml#EjbModule_" + id );
297 mapping.addChild( module );
298 modulemapXmlDom.addChild( mapping );
299 return mapping;
300 }
301 else if ( dependency.getType().equals( Constants.PROJECT_PACKAGING_WAR ) )
302 {
303 Xpp3Dom mapping = new Xpp3Dom( MODULEMAPS_MAPPINGS );
304 mapping.setAttribute( XMI_ID, "ModuleMapping_" + id );
305 mapping.setAttribute( MODULEMAPS_PROJECT_NAME, dependency.getArtifactId() );
306 Xpp3Dom module = new Xpp3Dom( APPLICATION_XML_MODULE );
307 module.setAttribute( XMI_TYPE, MODULEMAPS_APPLICATION_WEB_MODULE );
308 module.setAttribute( HREF, "META-INF/application.xml#WebModule_" + id );
309 mapping.addChild( module );
310 modulemapXmlDom.addChild( mapping );
311 return mapping;
312 }
313 else
314 {
315 Xpp3Dom utilityJARMapping = new Xpp3Dom( MODULEMAPS_UTILITY_JARMAPPINGS );
316 utilityJARMapping.setAttribute( XMI_ID, "UtilityJARMapping_" + id );
317 utilityJARMapping.setAttribute( MODULEMAPS_PROJECT_NAME, dependency.getArtifactId() );
318 utilityJARMapping.setAttribute( URI, dependency.getArtifactId() + ".jar" );
319 modulemapXmlDom.addChild( utilityJARMapping );
320 return utilityJARMapping;
321 }
322 }
323
324
325
326
327
328
329
330 private String getIdFromMapping( Xpp3Dom mapping )
331 {
332 if ( mapping.getChildCount() < 1 )
333 {
334 return "";
335 }
336 String href = mapping.getChild( 0 ).getAttribute( HREF );
337 String id = href.substring( href.indexOf( '#' ) + 1 );
338 return id;
339 }
340
341
342
343
344
345
346 private void handled( Xpp3Dom xpp3Dom )
347 {
348 for ( int index = 0; index < this.applicationXmlDomChildren.length; index++ )
349 {
350 if ( this.applicationXmlDomChildren[index] == xpp3Dom )
351 {
352 this.applicationXmlDomChildren[index] = null;
353 }
354 }
355 for ( int index = 0; index < this.modulemapsXmlDomChildren.length; index++ )
356 {
357 if ( this.modulemapsXmlDomChildren[index] == xpp3Dom )
358 {
359 this.modulemapsXmlDomChildren[index] = null;
360 }
361 }
362 }
363
364
365
366
367
368
369
370 private Xpp3Dom readXMLFile( File xmlFile )
371 {
372 try
373 {
374 Reader reader = new InputStreamReader( new FileInputStream( xmlFile ), "UTF-8" );
375 Xpp3Dom applicationXmlDom = Xpp3DomBuilder.build( reader );
376 return applicationXmlDom;
377 }
378 catch ( FileNotFoundException e )
379 {
380 return null;
381 }
382 catch ( Exception e )
383 {
384 log.error( Messages.getString( "EclipsePlugin.cantreadfile", xmlFile.getAbsolutePath() ) );
385
386 return null;
387 }
388 }
389
390
391
392
393
394
395
396 private void removeUnusedEntries( Xpp3Dom applicationXmlDom, Xpp3Dom modulemapsXmlDom )
397 {
398 for ( int index = 0; index < this.modulemapsXmlDomChildren.length; index++ )
399 {
400 if ( this.modulemapsXmlDomChildren[index] != null )
401 {
402 Xpp3Dom[] newModulemapsXmlDomChildren = modulemapsXmlDom.getChildren();
403 for ( int newIndex = 0; newIndex < newModulemapsXmlDomChildren.length; newIndex++ )
404 {
405 if ( ( newModulemapsXmlDomChildren[newIndex] != null )
406 && ( newModulemapsXmlDomChildren[newIndex] == this.modulemapsXmlDomChildren[index] ) )
407 {
408 modulemapsXmlDom.removeChild( newIndex );
409 break;
410 }
411 }
412 }
413 }
414 for ( int index = 0; index < this.applicationXmlDomChildren.length; index++ )
415 {
416 if ( this.applicationXmlDomChildren[index] != null )
417 {
418 Xpp3Dom[] newApplicationXmlDomChildren = applicationXmlDom.getChildren();
419 for ( int newIndex = 0; newIndex < newApplicationXmlDomChildren.length; newIndex++ )
420 {
421 if ( newApplicationXmlDomChildren[newIndex] == this.applicationXmlDomChildren[index] )
422 {
423 applicationXmlDom.removeChild( newIndex );
424 break;
425 }
426 }
427 }
428 }
429 }
430
431
432
433
434
435
436
437
438
439
440 private void updateApplicationXml( Xpp3Dom applicationXmlDom, Xpp3Dom modulemapXmlDom, IdeDependency dependency )
441 {
442 boolean isEar = Constants.PROJECT_PACKAGING_EJB.equals( dependency.getType() );
443 boolean isWar = Constants.PROJECT_PACKAGING_WAR.equals( dependency.getType() );
444
445 if ( dependency.isReferencedProject() || isEar || isWar )
446 {
447 Xpp3Dom mapping = findOrCreateArtifact( dependency, modulemapXmlDom );
448 handled( mapping );
449 if ( isEar )
450 {
451 Xpp3Dom module = findModuleInApplicationXml( applicationXmlDom, mapping );
452 if ( module == null )
453 {
454 module = new Xpp3Dom( APPLICATION_XML_MODULE );
455 module.setAttribute( ID, getIdFromMapping( mapping ) );
456 Xpp3Dom ejb = new Xpp3Dom( Constants.PROJECT_PACKAGING_EJB );
457 ejb.setValue( dependency.getArtifactId() + ".jar" );
458 module.addChild( ejb );
459 applicationXmlDom.addChild( module );
460 }
461 else
462 {
463 handled( module );
464 module.getChild( Constants.PROJECT_PACKAGING_EJB ).setValue( dependency.getArtifactId() + ".jar" );
465 }
466 }
467 else if ( isWar )
468 {
469 String contextRootInPom = getContextRootFor( dependency.getArtifactId() );
470 Xpp3Dom module = findModuleInApplicationXml( applicationXmlDom, mapping );
471 if ( module == null )
472 {
473 module = new Xpp3Dom( APPLICATION_XML_MODULE );
474 module.setAttribute( ID, getIdFromMapping( mapping ) );
475 Xpp3Dom web = new Xpp3Dom( APPLICATION_XML_WEB );
476 Xpp3Dom webUri = new Xpp3Dom( APPLICATION_XML_WEB_URI );
477 webUri.setValue( dependency.getArtifactId() + ".war" );
478 Xpp3Dom contextRoot = new Xpp3Dom( APPLICATION_XML_CONTEXT_ROOT );
479 contextRoot.setValue( contextRootInPom );
480 web.addChild( webUri );
481 web.addChild( contextRoot );
482 module.addChild( web );
483 applicationXmlDom.addChild( module );
484 }
485 else
486 {
487 handled( module );
488 module.getChild( APPLICATION_XML_WEB ).getChild( APPLICATION_XML_WEB_URI ).setValue(
489 dependency.getArtifactId()
490 + ".war" );
491 module.getChild( APPLICATION_XML_WEB ).getChild( APPLICATION_XML_CONTEXT_ROOT ).setValue(
492 contextRootInPom );
493 }
494 }
495 }
496 }
497
498
499
500
501
502
503
504 private String getContextRootFor( String artifactId )
505 {
506 for ( int index = 0; index < webModulesFromPoms.length; index++ )
507 {
508 if ( webModulesFromPoms[index].getChild( "artifactId" ).getValue().equals( artifactId ) )
509 return new File( webModulesFromPoms[index].getChild( "contextRoot" ).getValue() ).getName();
510 }
511 return artifactId;
512 }
513
514
515
516
517
518
519
520
521 private void writePrettyXmlFile( File xmlFile, Xpp3Dom xmlDomTree )
522 throws MojoExecutionException
523 {
524 Xpp3Dom original = readXMLFile( xmlFile );
525 if ( original != null && original.equals( xmlDomTree ) )
526 {
527 log.info( Messages.getString( "EclipsePlugin.unchangedmanifest", xmlFile.getAbsolutePath() ) );
528 return;
529 }
530 Writer w = null;
531 xmlFile.getParentFile().mkdirs();
532 try
533 {
534 w = new OutputStreamWriter( new FileOutputStream( xmlFile ), "UTF-8" );
535 }
536 catch ( IOException ex )
537 {
538 throw new MojoExecutionException( Messages.getString( "EclipsePlugin.erroropeningfile" ), ex );
539 }
540 XMLWriter writer = new PrettyPrintXMLWriter( w, "UTF-8", null );
541 Xpp3DomWriter.write( writer, xmlDomTree );
542 IOUtil.close( w );
543 }
544 }