We may want to have an attribute to indicate that a web.xml file is needed, or that we dont want to see the warning message. Say nowebxml="fail", "warn" or "skip", with the default being fail for backwards compatibility. Thoughts? Now is the time to add it... git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@468180 13f79535-47bb-0310-9956-ffa450edef68master
@@ -33,7 +33,20 @@ treatment for files that should end up in the | |||||
<p>(The War task is a shortcut for specifying the particular layout of a WAR file. | <p>(The War task is a shortcut for specifying the particular layout of a WAR file. | ||||
The same thing can be accomplished by using the <i>prefix</i> and <i>fullpath</i> | The same thing can be accomplished by using the <i>prefix</i> and <i>fullpath</i> | ||||
attributes of zipfilesets in a Zip or Jar task.)</p> | attributes of zipfilesets in a Zip or Jar task.)</p> | ||||
<p>The extended zipfileset element from the zip task (with attributes <i>prefix</i>, <i>fullpath</i>, and <i>src</i>) is available in the War task.</p> | |||||
<p>The extended zipfileset element from the zip task | |||||
(with attributes <i>prefix</i>, <i>fullpath</i>, and <i>src</i>) | |||||
is available in the War task. The task is also resource-enabled | |||||
and will add nested resources and resource collections to the archive.</p> | |||||
<p> | |||||
Before Servlet API 2.5/Java EE 5, a WEB-INF/web.xml file was mandatory in a | |||||
WAR file, so this task failed if the <code>webxml</code> attribute was missing. | |||||
As the web.xml file is now optional, the <code>webxml</code> attribute is now | |||||
downgraded to being optional. The task will warn if the file is not | |||||
included as an attribute or in a fileset, but still succeed. The task | |||||
will also complain if more than one web.xml file is added to the JAR. | |||||
</p> | |||||
<p><b>Please note that the zip format allows multiple files of the same | <p><b>Please note that the zip format allows multiple files of the same | ||||
fully-qualified name to exist within a single archive. This has been | fully-qualified name to exist within a single archive. This has been | ||||
@@ -55,13 +68,13 @@ to a value other than its default, <code>"add"</code>.</b></p> | |||||
</tr> | </tr> | ||||
<tr> | <tr> | ||||
<td valign="top">warfile</td> | <td valign="top">warfile</td> | ||||
<td valign="top"><i>Deprecated<i> name of the file to create | |||||
<td valign="top"><i>Deprecated</i> name of the file to create | |||||
-use <tt>destfile</tt> instead.</td> | -use <tt>destfile</tt> instead.</td> | ||||
</tr> | </tr> | ||||
<tr> | <tr> | ||||
<td valign="top">webxml</td> | <td valign="top">webxml</td> | ||||
<td valign="top">The deployment descriptor to use (WEB-INF/web.xml).</td> | <td valign="top">The deployment descriptor to use (WEB-INF/web.xml).</td> | ||||
<td valign="top" align="center">Yes, unless update is set to true</td> | |||||
<td valign="top" align="center">No (since Ant1.7)</td> | |||||
</tr> | </tr> | ||||
<tr> | <tr> | ||||
<td valign="top">basedir</td> | <td valign="top">basedir</td> | ||||
@@ -231,7 +244,7 @@ using Ant's default manifest file. The content of | |||||
directory, and thus it is our fault your webapp doesn't work. The cause | directory, and thus it is our fault your webapp doesn't work. The cause | ||||
of these complaints lies in WinZip, which turns an all upper-case | of these complaints lies in WinZip, which turns an all upper-case | ||||
directory into an all lower case one in a fit of helpfulness. Please check that | directory into an all lower case one in a fit of helpfulness. Please check that | ||||
jar xvf yourwebapp.war shows the same behaviour before filing another | |||||
<code>jar xvf yourwebapp.war</code> shows the same behaviour before filing another | |||||
report.<br/> | report.<br/> | ||||
Winzip has an option allowing all uppercase names (which is off by default!). It can be enabled by: | Winzip has an option allowing all uppercase names (which is off by default!). It can be enabled by: | ||||
Menu "Options" -> "Configuration", "View" property/tab page, then "General" group box has an option called "Allow all uppercase file names". | Menu "Options" -> "Configuration", "View" property/tab page, then "General" group box has an option called "Allow all uppercase file names". | ||||
@@ -20,6 +20,7 @@ package org.apache.tools.ant.taskdefs; | |||||
import java.io.File; | import java.io.File; | ||||
import java.io.IOException; | import java.io.IOException; | ||||
import java.util.Locale; | |||||
import org.apache.tools.ant.BuildException; | import org.apache.tools.ant.BuildException; | ||||
import org.apache.tools.ant.Project; | import org.apache.tools.ant.Project; | ||||
import org.apache.tools.ant.types.ZipFileSet; | import org.apache.tools.ant.types.ZipFileSet; | ||||
@@ -55,8 +56,10 @@ public class War extends Jar { | |||||
* flag set if the descriptor is added | * flag set if the descriptor is added | ||||
*/ | */ | ||||
private boolean descriptorAdded; | private boolean descriptorAdded; | ||||
private File addedWebXmlFile; | |||||
private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); | private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); | ||||
private static final String XML_DESCRIPTOR_PATH = "web-inf/web.xml"; | |||||
/** Constructor for the War Task. */ | /** Constructor for the War Task. */ | ||||
public War() { | public War() { | ||||
@@ -93,7 +96,7 @@ public class War extends Jar { | |||||
// Create a ZipFileSet for this file, and pass it up. | // Create a ZipFileSet for this file, and pass it up. | ||||
ZipFileSet fs = new ZipFileSet(); | ZipFileSet fs = new ZipFileSet(); | ||||
fs.setFile(deploymentDescriptor); | fs.setFile(deploymentDescriptor); | ||||
fs.setFullpath("WEB-INF/web.xml"); | |||||
fs.setFullpath(XML_DESCRIPTOR_PATH); | |||||
super.addFileset(fs); | super.addFileset(fs); | ||||
} | } | ||||
@@ -137,16 +140,18 @@ public class War extends Jar { | |||||
*/ | */ | ||||
protected void initZipOutputStream(ZipOutputStream zOut) | protected void initZipOutputStream(ZipOutputStream zOut) | ||||
throws IOException, BuildException { | throws IOException, BuildException { | ||||
// If no webxml file is specified, it's an error. | |||||
if (deploymentDescriptor == null && !isInUpdateMode()) { | |||||
throw new BuildException("webxml attribute is required", getLocation()); | |||||
} | |||||
super.initZipOutputStream(zOut); | super.initZipOutputStream(zOut); | ||||
} | } | ||||
/** | /** | ||||
* Overridden from Zip class to deal with web.xml | * Overridden from Zip class to deal with web.xml | ||||
* | |||||
* Here are cases that can arise | |||||
* -not a web.xml file : add | |||||
* -first web.xml : add, remember we added it | |||||
* -same web.xml again: skip | |||||
* -alternate web.xml : warn and skip | |||||
* | |||||
* @param file the file to add to the archive | * @param file the file to add to the archive | ||||
* @param zOut the stream to write to | * @param zOut the stream to write to | ||||
* @param vPath the name this entry shall have in the archive | * @param vPath the name this entry shall have in the archive | ||||
@@ -160,29 +165,51 @@ public class War extends Jar { | |||||
// not the one specified in the "webxml" attribute - or if | // not the one specified in the "webxml" attribute - or if | ||||
// it's being added twice, meaning the same file is specified | // it's being added twice, meaning the same file is specified | ||||
// by the "webxml" attribute and in a <fileset> element. | // by the "webxml" attribute and in a <fileset> element. | ||||
if (vPath.equalsIgnoreCase("WEB-INF/web.xml")) { | |||||
if (deploymentDescriptor == null | |||||
|| !FILE_UTILS.fileNameEquals(deploymentDescriptor, file) | |||||
|| descriptorAdded) { | |||||
log("Warning: selected " + archiveType | |||||
+ " files include a WEB-INF/web.xml which will be ignored " | |||||
+ "(please use webxml attribute to " | |||||
+ archiveType + " task)", Project.MSG_WARN); | |||||
String vPathLowerCase = vPath.toLowerCase(Locale.ENGLISH); | |||||
//by default, we add the file. | |||||
boolean addFile = true; | |||||
if (XML_DESCRIPTOR_PATH.equals(vPathLowerCase)) { | |||||
//a web.xml file was found. See if it is a duplicate or not | |||||
if (addedWebXmlFile != null) { | |||||
//a second web.xml file, so skip it | |||||
addFile = false; | |||||
//check to see if we warn or not | |||||
if (!FILE_UTILS.fileNameEquals(addedWebXmlFile, file)) { | |||||
log("Warning: selected " + archiveType | |||||
+" files include a second " +XML_DESCRIPTOR_PATH | |||||
+ " which will be ignored.\n" | |||||
+ "The duplicate entry is at " +file +'\n' | |||||
+ "The file that will be used is " | |||||
+ addedWebXmlFile, | |||||
Project.MSG_WARN); | |||||
} | |||||
} else { | } else { | ||||
super.zipFile(file, zOut, vPath, mode); | |||||
//no added file, yet | |||||
addedWebXmlFile=file; | |||||
//there is no web.xml file, so add it | |||||
addFile = true; | |||||
//and remember that we did | |||||
descriptorAdded = true; | descriptorAdded = true; | ||||
deploymentDescriptor = file; | |||||
} | } | ||||
} else { | |||||
} | |||||
if (addFile) { | |||||
super.zipFile(file, zOut, vPath, mode); | super.zipFile(file, zOut, vPath, mode); | ||||
} | } | ||||
} | } | ||||
/** | /** | ||||
* Make sure we don't think we already have a web.xml next time this task | * Make sure we don't think we already have a web.xml next time this task | ||||
* gets executed. | * gets executed. | ||||
*/ | */ | ||||
protected void cleanUp() { | protected void cleanUp() { | ||||
descriptorAdded = false; | |||||
if(addedWebXmlFile==null) { | |||||
log("No WEB-INF/web.xml file was added.\n" | |||||
+"This WAR file is only valid on Java EE 5+ runtimes\n" | |||||
+"and web servers that support v2.5 Web Applications"); | |||||
} | |||||
addedWebXmlFile = null; | |||||
super.cleanUp(); | super.cleanUp(); | ||||
} | } | ||||
} | } |
@@ -0,0 +1,113 @@ | |||||
<?xml version="1.0"?> | |||||
<project name="war-test" basedir="." default="all" | |||||
xmlns:au="antlib:org.apache.ant.antunit"> | |||||
<property name="working.dir" value="working"/> | |||||
<target name="all"> | |||||
<au:antunit> | |||||
<fileset file="${ant.file}"/> | |||||
<au:plainlistener/> | |||||
</au:antunit> | |||||
</target> | |||||
<target name="init"> | |||||
<delete dir="${working.dir}"/> | |||||
<mkdir dir="${working.dir}"/> | |||||
<property name="warfile" location="${working.dir}/test.war"/> | |||||
<property name="web.xml" location="web.xml"/> | |||||
<property name="webxml.generated" location="${working.dir}/WEB-INF/web.xml"/> | |||||
<!--failing on duplicates is half our testing--> | |||||
<presetdef name="mkwar"> | |||||
<war destfile="${warfile}" duplicate="fail"/> | |||||
</presetdef> | |||||
<presetdef name="expandwar"> | |||||
<unzip src="${working.dir}/test.war" dest="${working.dir}"/> | |||||
</presetdef> | |||||
</target> | |||||
<target name="tearDown"> | |||||
<delete dir="${working.dir}"/> | |||||
</target> | |||||
<!--test that you can patch a fileset reference into a lib element--> | |||||
<target name="testlibrefs" depends="init"> | |||||
<mkwar webxml="${web.xml}"> | |||||
<fileset id="test" dir="." includes="web.xml"/> | |||||
<lib refid="test"/> | |||||
</mkwar> | |||||
<expandwar/> | |||||
<au:assertFileExists file="${webxml.generated}" /> | |||||
</target> | |||||
<!-- | |||||
This checks that as of Java EE 5, the web.xml attr is optional. | |||||
Here there is a web.xml, in the webinf fileset, rather than a fileset | |||||
--> | |||||
<target name="testWebXmlInWebinf" depends="init"> | |||||
<mkwar> | |||||
<webinf dir="." includes="web.xml"/> | |||||
</mkwar> | |||||
<expandwar/> | |||||
<au:assertFileExists file="${webxml.generated}" /> | |||||
</target> | |||||
<target name="testDuplicateWebXml" depends="init"> | |||||
<mkwar webxml="${web.xml}" > | |||||
<webinf dir="." includes="web.xml"/> | |||||
<webinf file="${web.xml}"/> | |||||
<zipfileset file="${web.xml}" prefix="WEB-INF"/> | |||||
</mkwar> | |||||
<expandwar/> | |||||
<au:assertFileExists file="${webxml.generated}" /> | |||||
</target> | |||||
<target name="testDifferentDuplicateWebXml" depends="init"> | |||||
<copy file="${web.xml}" todir="${working.dir}" /> | |||||
<mkwar webxml="${web.xml}" > | |||||
<webinf dir="${working.dir}" includes="web.xml"/> | |||||
<webinf file="${web.xml}"/> | |||||
<zipfileset file="${web.xml}" prefix="WEB-INF"/> | |||||
</mkwar> | |||||
<expandwar/> | |||||
<au:assertFileExists file="${webxml.generated}" /> | |||||
<au:assertLogContains text="The duplicate entry is"/> | |||||
</target> | |||||
<!-- | |||||
this target does not have a web.xml file. | |||||
Instead it pulls in | |||||
--> | |||||
<target name="testWebXmlOptional" depends="init"> | |||||
<mkwar > | |||||
<classes dir="." includes="web.xml"/> | |||||
</mkwar> | |||||
<expandwar/> | |||||
<au:assertFileExists file="${working.dir}/WEB-INF/classes/web.xml" /> | |||||
<au:assertFalse> | |||||
<available file="${webxml.generated}" /> | |||||
</au:assertFalse> | |||||
<au:assertLogContains text="This WAR file is only valid on Java EE 5+ runtimes"/> | |||||
</target> | |||||
<target name="testClassesElement" depends="init"> | |||||
<mkwar > | |||||
<classes dir="." includes="web.xml"/> | |||||
</mkwar> | |||||
<expandwar/> | |||||
<au:assertFileExists file="${working.dir}/WEB-INF/classes/web.xml" /> | |||||
</target> | |||||
<target name="testLibElement" depends="init"> | |||||
<mkwar > | |||||
<lib dir="." includes="web.xml"/> | |||||
</mkwar> | |||||
<expandwar/> | |||||
<au:assertFileExists file="${working.dir}/WEB-INF/lib/web.xml" /> | |||||
</target> | |||||
</project> |
@@ -0,0 +1,5 @@ | |||||
<?xml version="1.0" encoding="UTF-8"?> | |||||
<web-app xmlns="http://java.sun.com/xml/ns/javaee" | |||||
version="2.5" metadata-complete="true"> | |||||
</web-app> |