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