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 }