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