2011/08/05 - Jakarta Cactus has been retired.

For more information, please explore the Attic.

View Javadoc

1   /* 
2    * ========================================================================
3    * 
4    * Licensed to the Apache Software Foundation (ASF) under one or more
5    * contributor license agreements.  See the NOTICE file distributed with
6    * this work for additional information regarding copyright ownership.
7    * The ASF licenses this file to You under the Apache License, Version 2.0
8    * (the "License"); you may not use this file except in compliance with
9    * the License.  You may obtain a copy of the License at
10   * 
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   * 
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   * 
19   * ========================================================================
20   */
21  package org.apache.cactus.maven2.mojos;
22  
23  import java.io.File;
24  import java.io.FileInputStream;
25  import java.io.IOException;
26  import java.util.Iterator;
27  
28  import org.apache.cactus.integration.api.version.Version;
29  import org.apache.maven.archiver.MavenArchiveConfiguration;
30  import org.apache.maven.archiver.MavenArchiver;
31  import org.apache.maven.artifact.DependencyResolutionRequiredException;
32  import org.apache.maven.plugin.AbstractMojo;
33  import org.apache.maven.plugin.MojoExecutionException;
34  import org.apache.maven.plugin.MojoFailureException;
35  import org.apache.maven.plugin.assembly.archive.ArchiveExpansionException;
36  import org.apache.maven.plugin.assembly.utils.AssemblyFileUtils;
37  import org.apache.maven.project.MavenProject;
38  import org.codehaus.cargo.module.application.ApplicationXml;
39  import org.codehaus.cargo.module.application.ApplicationXmlIo;
40  import org.codehaus.cargo.module.application.DefaultEarArchive;
41  import org.codehaus.cargo.module.application.EarArchive;
42  import org.codehaus.cargo.module.ejb.EjbArchive;
43  import org.codehaus.cargo.module.ejb.EjbJarXml;
44  import org.codehaus.cargo.module.ejb.Entity;
45  import org.codehaus.cargo.module.ejb.Session;
46  import org.codehaus.cargo.module.webapp.EjbRef;
47  import org.codehaus.plexus.archiver.ArchiverException;
48  import org.codehaus.plexus.archiver.ear.EarArchiver;
49  import org.codehaus.plexus.archiver.jar.ManifestException;
50  import org.codehaus.plexus.archiver.manager.ArchiverManager;
51  import org.codehaus.plexus.archiver.manager.NoSuchArchiverException;
52  import org.codehaus.plexus.archiver.war.WarArchiver;
53  import org.codehaus.plexus.util.FileUtils;
54  import org.jdom.JDOMException;
55  /**
56   * A maven2 mojo that injects elements necessary to run Cactus tests into an
57   * existing EAR file.
58   * 
59   * @version $Id: CactifyEarMojo.java 394252 2008-04-29 04:20:17Z ptahchiev $
60   * @goal cactifyear
61   * @requiresDependencyResolution compile
62   */
63  public class CactifyEarMojo extends AbstractMojo
64  {
65      /**
66       * Cactus war configuration holder.
67       * @parameter
68       */
69      private CactifyWarMojo cactusWar;
70      
71      /**
72       * The archive that contains the web-app that should be cactified.
73       * @required
74       * @parameter
75       */
76      private File srcFile;
77      
78      /**
79       * The archive that contains the web-app that should be cactified.
80       * @parameter
81       * default-value="${project.build.directory}/${project.artifactId}-cactified.ear"
82       */
83      private File destFile;
84  
85      /**
86       * Indicates whether or not we should add ejb references to local ejbs
87       * in the deployment descriptor.
88       * @parameter
89       */
90      private boolean addEjbReferences;
91      
92      /**
93       * The Ear archiver.
94       *
95       * @parameter expression="${component.org.codehaus.plexus.archiver.Archiver#ear}"
96       * @required
97       */
98      private EarArchiver earArchiver;
99      
100     /**
101      * The War archiver.
102      *
103      * @parameter expression="${component.org.codehaus.plexus.archiver.Archiver#war}"
104      * @required
105      */
106     private WarArchiver warArchiver;
107     
108     /**
109      * The maven archive configuration to use.
110      *
111      * @parameter
112      */
113     private MavenArchiveConfiguration archive = new MavenArchiveConfiguration();
114     
115     /**
116      * The maven project.
117      *
118      * @parameter expression="${project}"
119      * @required
120      * @readonly
121      */
122     private MavenProject project;
123     
124     /**
125      * The archive manager.
126      * @component
127      */
128     private ArchiverManager archiverManager;
129     
130     /**
131      * The "main" method of the mojo.
132      * @throws MojoExecutionException in case an error occurs.
133      * @throws MojoFailureException in case a failure occurs.
134      */
135 	public void execute() throws MojoExecutionException, MojoFailureException 
136 	{
137         if (cactusWar == null)
138         {
139             cactusWar = createCactusWarConfig();
140         }
141         
142         if (getSrcFile() == null) 
143         {
144             throw new MojoExecutionException("You need to specify [srcFile] "
145             		+ "attribute for cactification!");
146         }
147         MavenArchiver archiver = new MavenArchiver();
148         archiver.setArchiver(earArchiver);
149         
150         //Add everything that's in the source EAR to the destination EAR
151         File tempLocation = null;
152         
153         tempLocation = FileUtils.createTempFile("cactus", "explode.tmp.dir",
154                 getProject().getBasedir());
155         tempLocation.mkdirs();
156         tempLocation.deleteOnExit();
157         
158         try 
159         {
160             if (this.srcFile != null)
161             {
162                 AssemblyFileUtils.unpack(this.srcFile, tempLocation,
163                     archiverManager);
164             }
165         } 
166         catch (ArchiveExpansionException e) 
167         {
168             throw new MojoExecutionException("Error extracting the"
169                    + " archive.", e);
170         } 
171         catch (NoSuchArchiverException e) 
172         {
173             throw new MojoExecutionException("Problem reading the "
174                    + "source archive.", e);
175         }
176         
177         try 
178         {
179 			earArchiver.addDirectory(tempLocation);
180 		} 
181         catch (ArchiverException e1) 
182         {
183 			// Cannot add the temp location for some reason.
184         	throw new MojoExecutionException("Problem adding the source " +
185         			"files to the dest. archive ", e1);
186 		}
187         
188         // cactify the application.xml
189         ApplicationXml appXml = null;
190         try 
191         {
192             appXml = getOriginalApplicationXml();
193         } 
194         catch (JDOMException e) 
195         {
196             throw new MojoExecutionException("Unable to get the "
197                + "original application.xml", e);
198         }
199         
200         File tmpAppXml = cactifyApplicationXml(appXml);
201         
202         try 
203         {
204             earArchiver.addDirectory(tempLocation);
205             earArchiver.setAppxml(tmpAppXml);
206             
207             archiver.setOutputFile(getDestFile());
208             
209             // create the cactus war
210             File cactusWarFile = createCactusWarFile();
211             addFileToEar(cactusWarFile, cactusWar.getFileName());
212             
213             archiver.createArchive(getProject(), getArchive());
214         }
215         catch (ArchiverException aex)
216         {
217             throw new MojoExecutionException("Error while performing the "
218                     + "cactified archive.", aex);
219         } 
220         catch (ManifestException me) 
221         {
222             throw new MojoExecutionException("Error reading the manifest "
223                    + "data in the original file.", me);
224         } 
225         catch (IOException ioe) 
226         {
227             throw new MojoExecutionException("Input/output exception occured ",
228                     ioe);
229         }
230         catch (DependencyResolutionRequiredException de) 
231         {
232             throw new MojoExecutionException("Problem with resolving the"
233                     + " dependencies of the project. ", de);
234         }
235         finally
236         {
237             try 
238             {
239                 if (tempLocation != null)
240                 {
241                     FileUtils.deleteDirectory(tempLocation);
242                 }
243             } 
244             catch (IOException e) 
245             {
246                 throw new MojoExecutionException("Error deleting temporary "
247                        + "folder", e);
248             }
249         }
250 	}
251     
252     /**
253      * A helper method to create a temporary file.
254      * @return the cactus.war
255      * @throws MojoExecutionException in case a runtime error occurs.
256      * @throws MojoFailureException in case a mojo failure occurs.
257      */
258     private File createCactusWarFile() throws MojoExecutionException, MojoFailureException
259     {
260         File tmpCactusWar = FileUtils.createTempFile("cactus", "cactus.war",
261                                                      getProject().getBasedir());
262         tmpCactusWar.deleteOnExit();
263         cactusWar.setDestFile(tmpCactusWar);
264         cactusWar.setWarArchiver(this.warArchiver);
265         cactusWar.setProject(this.project);
266         
267         if (addEjbReferences)
268         {
269             try 
270             {
271                 addEjbReferencesToWar(tmpCactusWar);
272             } 
273             catch (JDOMException e) 
274             {
275                 throw new MojoExecutionException(
276                         "Unable to add ejb-references", e);
277             }
278         }
279         
280         cactusWar.execute();
281         
282         return tmpCactusWar;
283     }
284     
285     /**
286      * 
287      * @param theAppXml the application.xml to cactify
288      * @return the cactified application.xml
289      * @throws MojoExecutionException 
290      */
291     private File cactifyApplicationXml(ApplicationXml theAppXml) 
292                                             throws MojoExecutionException
293     {
294         theAppXml.addWebModule(cactusWar.getFileName(), cactusWar.getContext());
295         // serialize the cactified app xml
296         //FileUtils fileUtils = FileUtils.newFileUtils();
297         File tmpAppXml = FileUtils.createTempFile("cactus", "application.xml",
298                                                   getProject().getBasedir());
299         tmpAppXml.deleteOnExit();
300         try
301         {
302             ApplicationXmlIo.writeApplicationXml(theAppXml, 
303                                                  tmpAppXml, 
304                                                  null, true);
305         }
306         catch (IOException ioe)
307         {
308             throw new MojoExecutionException(
309                 "Could not write temporary deployment descriptor", ioe);
310         }
311         return tmpAppXml;
312     }
313     
314     /**
315      * 
316      * @return the application.xml from the source ear
317      * @throws JDOMException in case a JDOM exception is thrown
318      * @throws MojoExecutionException 
319      */
320     private ApplicationXml getOriginalApplicationXml() 
321                             throws JDOMException, MojoExecutionException
322     {
323         ApplicationXml appXml = null;
324         try
325         {
326             EarArchive ear = new DefaultEarArchive(
327                 new FileInputStream(this.srcFile));
328             
329             appXml = ear.getApplicationXml();
330             if (appXml == null)
331             {
332                 throw new MojoExecutionException("The EAR source file does not "
333                     + "contain a META-INF/application.xml " 
334                     + "deployment descriptor");
335             }
336         }
337         catch (IOException e)
338         {
339             throw new MojoExecutionException("Failed to open EAR", e);
340         }
341         
342         return appXml;
343     }
344 
345     /**
346      * 
347      * @param theFile the file to add
348      * @param theFullPath the path within the ear
349      * @throws ArchiverException in case the adding is impossible.
350      */
351     private void addFileToEar(File theFile, String theFullPath) 
352                                                     throws ArchiverException
353     {
354         earArchiver.addFile(theFile, theFullPath);
355     }
356     
357     /**
358      * Add ejb references.
359      * 
360      * @param theWar temporary cactus war
361      * @throws JDOMException in case a parse exception is thrown 
362      * @throws MojoExecutionException in case any other error occurs.
363      */
364     private void addEjbReferencesToWar(File theWar) 
365                     throws JDOMException, MojoExecutionException 
366     {
367         try
368         {
369             EarArchive ear = new DefaultEarArchive(
370                 new FileInputStream(srcFile));
371             ApplicationXml appXml = ear.getApplicationXml();
372             Iterator ejbModules = appXml.getEjbModules();
373             while (ejbModules.hasNext())
374             {
375                 String module = (String) ejbModules.next();
376                 EjbArchive ejbArchive = ear.getEjbModule(module);
377                 EjbJarXml descr = ejbArchive.getEjbJarXml();
378                 Iterator vendorDescrIterator = descr.getVendorDescriptors();
379                 if (vendorDescrIterator == null 
380                     || !vendorDescrIterator.hasNext())
381                 {
382                     throw new MojoExecutionException("Failed to find vendor " 
383                                              + "deployment descriptor " 
384                                              + "for ejb jar " + module);
385                 }
386                 
387                 Iterator ejbs = descr.getSessionEjbs();
388                 while (ejbs.hasNext())
389                 {
390                     Session ejb = (Session) ejbs.next();
391                     String name = ejb.getName();
392                     String local = ejb.getLocal();
393                     String localHome = ejb.getLocalHome();
394                     if (local != null)
395                     {
396                         getLog().debug("Adding ejb-ref for local session ejb "
397                             + ejb.getName());
398                         EjbRef ref = new EjbRef();
399                         ref.setType("Session");
400                         ref.setEjbName(name);
401                         ref.setName("ejb/" + name);
402                         ref.setEjbInterface(local);
403                         ref.setEjbHomeInterface(localHome);
404                         ref.setLocal(true);
405                         
406                         cactusWar.addConfiguredEjbref(ref);
407                     }
408                 }
409                 ejbs = descr.getEntityEjbs();
410                 while (ejbs.hasNext())
411                 {
412                     Entity ejb = (Entity) ejbs.next();
413                     String name = ejb.getName();
414                     String local = ejb.getLocal();
415                     String localHome = ejb.getLocalHome();
416                     if (local != null)
417                     {
418                         getLog().debug("Adding ejb-ref for local entity ejb "
419                             + ejb.getName());
420                         EjbRef ref = new EjbRef();
421                         ref.setType("Entity");
422                         ref.setEjbName(name);
423                         ref.setName("ejb/" + name);
424                         ref.setEjbInterface(local);
425                         ref.setEjbHomeInterface(localHome);
426                         ref.setLocal(true);
427                         
428                         cactusWar.addConfiguredEjbref(ref);
429                     }
430                 }
431             }
432         }
433         catch (IOException e)
434         {
435             throw new MojoExecutionException("Could not merge deployment " 
436                                      + "descriptors", e);
437         }
438     }
439     
440     /**
441      * Initialize cactusWar with some default values.
442      *
443      * @return the CactusWar configuration
444      */
445     private CactifyWarMojo createCactusWarConfig()
446     {
447         CactifyWarMojo cactusWarConfig = new CactifyWarMojo();
448         Version version = new Version();
449         version.setValue("2.3");
450         cactusWarConfig.setVersion(version);
451         cactusWarConfig.setContext("/cactus");
452         cactusWarConfig.setWarArchiver(warArchiver);
453         cactusWarConfig.setProject(getProject());
454         
455         return cactusWarConfig;
456     }
457     
458     /**
459      * Getter method for the MavenProject.
460      * @return the MavenProject
461      */
462     public MavenProject getProject()
463     {
464         return project;
465     }
466     
467     /**
468      * Getter method for the MavenArchiveConfiguration.
469      * @return the MavenArchiveConfiguration
470      */
471     public MavenArchiveConfiguration getArchive()
472     {
473         return archive;
474     }
475     
476     /**
477      * Getter method for the destFile.
478      * @return
479      */
480     public File getDestFile() 
481     {
482         return destFile;
483     }
484     
485     /**
486      * Getter method for the srcFile.
487      * @return
488      */
489     public File getSrcFile() 
490     {
491         return srcFile;
492     }
493 
494 }