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