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