Ok, I took a stab at it. It works, although its somewhat ugly. I modified 'AbstractWarMojo.java' to read in a war dependency, overlay it on the build directory files, and merge both wars' web.xml files (by way of org.codehaus.cargo.module.webapp.WebXmlMerger). It works, which is good enough for me. It should probably be in a different plugin, but this was doable for today...

*** Start AbstractWarMojo.java ***
package org.apache.maven.plugin.war;

/*
* Copyright 2001-2005 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import org.apache.commons.io.IOUtils;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.project.MavenProject;
import org.codehaus.cargo.module.webapp.WebXml;
import org.codehaus.plexus.util.DirectoryScanner;
import org.codehaus.plexus.util.FileUtils;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter;

public abstract class AbstractWarMojo
   extends AbstractMojo
{
   /**
    * The maven project.
    *
    * @parameter expression="${project}"
    * @required
    * @readonly
    */
   private MavenProject project;

   /**
    * The directory containing generated classes.
    *
    * @parameter expression="${project.build.outputDirectory}"
    * @required
    * @readonly
    */
   private File classesDirectory;

   /**
    * The directory where the webapp is built.
    *
* @parameter expression="${project.build.directory}/${project.build.finalName}"
    * @required
    */
   private File webappDirectory;

   /**
    * Single directory for extra files to include in the WAR.
    *
    * @parameter expression="${basedir}/src/main/webapp"
    * @required
    */
   private File warSourceDirectory;

   /**
    * The path to the web.xml file to use.
    *
    * @parameter expression="${maven.war.webxml}"
    */
   private String webXml;

   public static final String WEB_INF = "WEB-INF";

   /**
    * The comma separated list of tokens to include in the WAR.
    * Default is '**'.
    *
    * @parameter alias="includes"
    */
   private String warSourceIncludes = "**";

   /**
    * The comma separated list of tokens to exclude from the WAR.
    *
    * @parameter alias="excludes"
    */
   private String warSourceExcludes;

   private static final String[] EMPTY_STRING_ARRAY = {};

   public abstract void execute()
       throws MojoExecutionException;

   public MavenProject getProject()
   {
       return project;
   }

   public void setProject( MavenProject project )
   {
       this.project = project;
   }

   public File getClassesDirectory()
   {
       return classesDirectory;
   }

   public void setClassesDirectory( File classesDirectory )
   {
       this.classesDirectory = classesDirectory;
   }

   public File getWebappDirectory()
   {
       return webappDirectory;
   }

   public void setWebappDirectory( File webappDirectory )
   {
       this.webappDirectory = webappDirectory;
   }

   public File getWarSourceDirectory()
   {
       return warSourceDirectory;
   }

   public void setWarSourceDirectory( File warSourceDirectory )
   {
       this.warSourceDirectory = warSourceDirectory;
   }

   public String getWebXml()
   {
       return webXml;
   }

   public void setWebXml( String webXml )
   {
       this.webXml = webXml;
   }

   /**
    * Returns a string array of the excludes to be used
    * when assembling/copying the war.
    *
    * @return an array of tokens to exclude
    */
   protected String[] getExcludes()
   {
List excludeList = new ArrayList( FileUtils.getDefaultExcludesAsList() );
       if ( warSourceExcludes != null && !"".equals( warSourceExcludes ) )
       {
           excludeList.add( warSourceExcludes );
       }

       // if webXML is specified, omit the one in the source directory
       if ( getWebXml() != null && !"".equals( getWebXml() ) )
       {
           excludeList.add( "**/" + WEB_INF + "/web.xml" );
       }

       return (String[]) excludeList.toArray( EMPTY_STRING_ARRAY );
   }

   /**
    * Returns a string array of the includes to be used
    * when assembling/copying the war.
    *
    * @return an array of tokens to include
    */
   protected String[] getIncludes()
   {
       return new String[]{warSourceIncludes};
   }

   public void buildExplodedWebapp( File webappDirectory )
       throws MojoExecutionException
   {
       getLog().info( "Exploding webapp..." );

       webappDirectory.mkdirs();

       File webinfDir = new File( webappDirectory, WEB_INF );

       webinfDir.mkdirs();

       try
       {
copyResources( getWarSourceDirectory(), webappDirectory, getWebXml() );

           buildWebapp( getProject(), webappDirectory );
       }
       catch ( IOException e )
       {
throw new MojoExecutionException( "Could not explode webapp...", e );
       }
   }

   /**
    * Copies webapp resources from the specified directory.
    * <p/>
    * Note that the <tt>webXml</tt> parameter could be null and may
    * specify a file which is not named <tt>web.xml<tt>. If the file
    * exists, it will be copied to the <tt>META-INF</tt> directory and
    * renamed accordingly.
    *
    * @param sourceDirectory the source directory
    * @param webappDirectory the target directory
    * @param webXml the path to a custom web.xml
* @throws java.io.IOException if an error occured while copying resources
    */
public void copyResources( File sourceDirectory, File webappDirectory, String webXml )
       throws IOException
   {
       if ( !sourceDirectory.equals( webappDirectory ) )
       {
getLog().info( "Copy webapp resources to " + webappDirectory.getAbsolutePath() );
           if ( getWarSourceDirectory().exists() )
           {
               String[] fileNames = getWarFiles( sourceDirectory );
               for ( int i = 0; i < fileNames.length; i++ )
               {
FileUtils.copyFile( new File( sourceDirectory, fileNames[i] ), new File( webappDirectory, fileNames[i] ) );
               }
           }

           if ( webXml != null && !"".equals( webXml ) )
           {
               //rename to web.xml
               File webinfDir = new File( webappDirectory, WEB_INF );
FileUtils.copyFile( new File( webXml ), new File( webinfDir, "/web.xml" ) );
           }
       }
   }

   /**
    * Builds the webapp for the specified project.
    * <p/>
    * Classes, libraries and tld files are copied to
    * the <tt>webappDirectory</tt> during this phase.
    *
    * @param project the maven project
    * @param webappDirectory
* @throws java.io.IOException if an error occured while building the webapp
    */
   public void buildWebapp( MavenProject project, File webappDirectory )
       throws IOException, MojoExecutionException
   {
getLog().info( "Assembling webapp " + project.getArtifactId() + " in " + webappDirectory );

       File libDirectory = new File( webappDirectory, WEB_INF + "/lib" );

       File tldDirectory = new File( webappDirectory, WEB_INF + "/tld" );

File webappClassesDirectory = new File( webappDirectory, WEB_INF + "/classes" );

if ( getClassesDirectory().exists() && (!getClassesDirectory().equals(webappClassesDirectory)))
       {
FileUtils.copyDirectoryStructure( getClassesDirectory(), webappClassesDirectory );
       }

       Set artifacts = project.getArtifacts();

       for ( Iterator iter = artifacts.iterator(); iter.hasNext(); )
       {
           Artifact artifact = (Artifact) iter.next();

           // TODO: utilise appropriate methods from project builder
ScopeArtifactFilter filter = new ScopeArtifactFilter( Artifact.SCOPE_RUNTIME );
           if ( !artifact.isOptional() && filter.include( artifact ) )
           {
               String type = artifact.getType();
               if ( "tld".equals( type ) )
               {
FileUtils.copyFileToDirectory( artifact.getFile(), tldDirectory );
               }
else if ( "jar".equals( type ) || "ejb".equals( type ) || "ejb-client".equals( type ) )
               {
FileUtils.copyFileToDirectory( artifact.getFile(), libDirectory );
               }
               else if("war".equals( type ))
               {
FileInputStream warInp = new FileInputStream(artifact.getFile());
                   ZipInputStream zipInp = new ZipInputStream(warInp);
                   ZipEntry zipEntry = null;

                   while ((zipEntry = zipInp.getNextEntry()) != null) {
                       File entryFile = new File(webappDirectory, zipEntry
                               .getName());

                       if (zipEntry.isDirectory()) {
                           entryFile.mkdirs();
                       } else {
if(zipEntry.getName().indexOf("web.xml") > -1 && entryFile.exists())
                           {
                               try
                               {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
                                   IOUtils.copy(zipInp, byteOut);
String webXmlString = byteOut.toString();
                                   System.out.println(webXmlString);
Document zipWebXmlDoc = docBuilder.parse(new InputSource(new StringReader(webXmlString))); Document currWebXmlDoc = docBuilder.parse(entryFile); WebXml zipWebXml = new WebXml(zipWebXmlDoc); WebXml currWebXml = new WebXml(currWebXmlDoc); org.codehaus.cargo.module.webapp.WebXmlMerger merger = new org.codehaus.cargo.module.webapp.WebXmlMerger(currWebXml);
                                   merger.merge(zipWebXml);
Transformer transformer = TransformerFactory.newInstance().newTransformer(); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); // initialize StreamResult with File object to save to file StreamResult result = new StreamResult(new StringWriter()); DOMSource source = new DOMSource(currWebXmlDoc);
                                   transformer.transform(source, result);
String xmlString = result.getWriter().toString(); FileWriter fileOut = new FileWriter(entryFile); PrintWriter outp = new PrintWriter(fileOut); outp.print(xmlString);
                                   outp.flush();
                                   outp.close();
                                   fileOut.close();
                               }
                               catch(Exception e)
                               {
                                   e.printStackTrace();
throw new MojoExecutionException("Error merging web.xml files", e);
                               }
                           }
                           else
                           {
FileOutputStream outp = new FileOutputStream(
                                       entryFile, false);
                               IOUtils.copy(zipInp, outp);
                           }
                       }
                   }
               } else
               {
getLog().debug( "Skipping artifact of type " + type + " for WEB-INF/lib" );
               }
           }
       }
   }

   /**
* Returns a list of filenames that should be copied over to the destination
    * directory.
    *
    * @param sourceDir
    *            the directory to be scanned
    * @return the array of filenames, relative to the sourceDir
    */
   private String[] getWarFiles( File sourceDir )
   {
       DirectoryScanner scanner = new DirectoryScanner();
       scanner.setBasedir( sourceDir );
       scanner.setExcludes( getExcludes() );
       scanner.addDefaultExcludes();

       scanner.setIncludes( getIncludes() );

       scanner.scan();

       return scanner.getIncludedFiles();
   }
}
*** End AbstractWarMojo.java ***

Also had to change the pom.xml to add dependencies...

<dependency>
     <groupId>commons-io</groupId>
     <artifactId>commons-io</artifactId>
     <version>1.1</version>
   </dependency>
   <dependency>
     <groupId>xerces</groupId>
     <artifactId>xerces</artifactId>
     <version>2.4.0</version>
   </dependency>
   <dependency>
     <groupId>cargo</groupId>
     <artifactId>cargo</artifactId>
     <version>0.6</version>
   </dependency>


Good luck all...

Kevin Galligan wrote:

This concept has been floating around the list for a while.  I've got
the same problem.  I'm hoping somebody has a solution or at least a good
idea of what road to go down. I'd be happy to try coding something, but I have a feeling that somebody is already working on this. If not, any thoughts on where to look?

war plugin?
new plugin?
something else?

I've got this to work with the assembly plugin, but it would only work
with a jar or zip output, which would then have to be renamed to war.
Not horrible, but there's an easier way to do it. This approach also has some other issues:

- No web.xml merging
- No automatic support of things like 'war:exploded'
- Generally breaks the concept of project descriptor being enough info to build a project. You should be able to specify a particular war artifact as a dependency and have it included in your current war project.

Any thoughts or comments welcome. Kind of lost at this point. In a general sense, I think there should be a way to include common web application components inside a web application project. Similar to including java classes in dependent jars. Reusing the code. We do this currently with file sharing in visual source safe, but that sucks, and I'm trying to move us off vss anyway.

Thanks,

-Kevin

[EMAIL PROTECTED] wrote:




I want to combine 2 war files into 1, so I have a war project with a subset of functionallity. I then have another war project that I want to depend
on the first war project with.  I would then have tasks to unwar the war
file, so that the files from both wars can then be war'ed up together.

However, when using a war project, any war type dependencies don't get
transferred into the /target folder (tried test, compile, runtime, and
provided).

When using an ear project, the war dependencies get transferred into the
/target folder, and that is exactly what I need, just for a war project.

Any ideas??
___________________________________
Damian Bradicich
Software Developer
Scientific Technologies Corporation
Tel: (603) 471-4712
Email: [EMAIL PROTECTED]
Web Site: www.stchome.com
"Advancing Public Health Outcomes Through Information Technology"
___________________________________


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]




---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to