git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@349639 13f79535-47bb-0310-9956-ffa450edef68master
@@ -12,7 +12,7 @@ | |||||
<h3>Description</h3> | <h3>Description</h3> | ||||
<p>Signs JAR files with the <tt>jarsigner</tt> command line tool. | <p>Signs JAR files with the <tt>jarsigner</tt> command line tool. | ||||
It will take a named file in the <tt>jar</tt> attribute, and an optional | It will take a named file in the <tt>jar</tt> attribute, and an optional | ||||
<tt>destDir</tt> or <tt>signedJar</tt> attribute. Nested filesets are also | |||||
<tt>destDir</tt> or <tt>signedJar</tt> attribute. Nested paths are also | |||||
supported; here only an (optional) <tt>destDir</tt> is allowed. If a destination | supported; here only an (optional) <tt>destDir</tt> is allowed. If a destination | ||||
directory or explicit JAR file name is not provided, JARs are signed in place. | directory or explicit JAR file name is not provided, JARs are signed in place. | ||||
</p> | </p> | ||||
@@ -39,7 +39,7 @@ and <tt>lazy</tt> is false, the JAR is signed.</li> | |||||
<tr> | <tr> | ||||
<td valign="top">jar</td> | <td valign="top">jar</td> | ||||
<td valign="top">the jar file to sign</td> | <td valign="top">the jar file to sign</td> | ||||
<td valign="top" align="center">Yes, unless nested filesets have | |||||
<td valign="top" align="center">Yes, unless nested paths have | |||||
been used.</td> | been used.</td> | ||||
</tr> | </tr> | ||||
<tr> | <tr> | ||||
@@ -134,6 +134,11 @@ block</td> | |||||
<td valign="top"><b>Description</b></td> | <td valign="top"><b>Description</b></td> | ||||
<td align="center" valign="top"><b>Required</b></td> | <td align="center" valign="top"><b>Required</b></td> | ||||
</tr> | </tr> | ||||
<tr> | |||||
<td valign="top">path</td> | |||||
<td valign="top">path of JAR files to sign. <em>since Ant 1.7</em></td> | |||||
<td valign="top" align="center">No</td> | |||||
</tr> | |||||
<tr> | <tr> | ||||
<td valign="top">fileset</td> | <td valign="top">fileset</td> | ||||
<td valign="top">fileset of JAR files to sign. </td> | <td valign="top">fileset of JAR files to sign. </td> | ||||
@@ -167,7 +172,9 @@ alias="apache-group" storepass="secret"/> | |||||
alias="testonly" keystore="testkeystore" | alias="testonly" keystore="testkeystore" | ||||
storepass="apacheant" | storepass="apacheant" | ||||
preservelastmodified="true"> | preservelastmodified="true"> | ||||
<fileset dir="dist" includes="**/*.jar" /> | |||||
<path> | |||||
<fileset dir="dist" includes="**/*.jar" /> | |||||
</path> | |||||
<flattenmapper /> | <flattenmapper /> | ||||
</signjar> | </signjar> | ||||
</pre></blockquote> | </pre></blockquote> | ||||
@@ -183,7 +190,9 @@ all be copied to this directory, not to subdirectories. | |||||
storepass="apacheant" | storepass="apacheant" | ||||
lazy="true" | lazy="true" | ||||
> | > | ||||
<fileset dir="dist" includes="**/*.jar" /> | |||||
<path> | |||||
<fileset dir="dist" includes="**/*.jar" /> | |||||
</path> | |||||
</signjar> | </signjar> | ||||
</pre></blockquote> | </pre></blockquote> | ||||
<p> | <p> | ||||
@@ -118,6 +118,32 @@ | |||||
</sign-base> | </sign-base> | ||||
</target> | </target> | ||||
<target name="testPath" depends="jar"> | |||||
<sign-base> | |||||
<path> | |||||
<fileset file="${test.jar}" /> | |||||
</path> | |||||
</sign-base> | |||||
<assertSigned/> | |||||
</target> | |||||
<target name="testPathAndJar" depends="jar"> | |||||
<sign-base jar="${test.jar}" lazy="true"> | |||||
<path> | |||||
<fileset file="${test.jar}" /> | |||||
</path> | |||||
</sign-base> | |||||
<assertSigned/> | |||||
</target> | |||||
<target name="testPathAndSignedJar" depends="jar"> | |||||
<sign-base signedjar="${sign.dir}/newfile.jar"> | |||||
<path> | |||||
<fileset file="${test.jar}" /> | |||||
</path> | |||||
</sign-base> | |||||
</target> | |||||
<target name="testSignedJar" depends="jar"> | <target name="testSignedJar" depends="jar"> | ||||
<sign signedjar="${subdirtest.jar}"/> | <sign signedjar="${subdirtest.jar}"/> | ||||
<assertSigned jar="${subdirtest.jar}"/> | <assertSigned jar="${subdirtest.jar}"/> | ||||
@@ -139,6 +165,15 @@ | |||||
<assertSigned jar="${subdirtest.jar}"/> | <assertSigned jar="${subdirtest.jar}"/> | ||||
</target> | </target> | ||||
<target name="testDestDirPath" depends="jar"> | |||||
<sign-base destDir="${subdir}"> | |||||
<path> | |||||
<fileset file="${test.jar}" /> | |||||
</path> | |||||
</sign-base> | |||||
<assertSigned jar="${subdirtest.jar}"/> | |||||
</target> | |||||
<target name="testMapperNoDest" depends="jar"> | <target name="testMapperNoDest" depends="jar"> | ||||
<sign-base > | <sign-base > | ||||
<flattenmapper /> | <flattenmapper /> | ||||
@@ -154,6 +189,16 @@ | |||||
<assertSigned jar="${subdirtest.jar}"/> | <assertSigned jar="${subdirtest.jar}"/> | ||||
</target> | </target> | ||||
<target name="testMapperPath" depends="jar"> | |||||
<sign-base destDir="${subdir}"> | |||||
<path> | |||||
<pathelement location="${test.jar}" /> | |||||
</path> | |||||
<flattenmapper /> | |||||
</sign-base> | |||||
<assertSigned jar="${subdirtest.jar}"/> | |||||
</target> | |||||
<target name="testTwoMappers" depends="jar"> | <target name="testTwoMappers" depends="jar"> | ||||
<sign-base destDir="${subdir}"> | <sign-base destDir="${subdir}"> | ||||
<fileset file="${test.jar}" /> | <fileset file="${test.jar}" /> | ||||
@@ -211,6 +256,14 @@ | |||||
</verify-base> | </verify-base> | ||||
</target> | </target> | ||||
<target name="testVerifyPath" depends="basic"> | |||||
<verify-base > | |||||
<path> | |||||
<pathelement location="${test.jar}" /> | |||||
</path> | |||||
</verify-base> | |||||
</target> | |||||
<target name="testVerifyNoArgs"> | <target name="testVerifyNoArgs"> | ||||
<verify-base /> | <verify-base /> | ||||
</target> | </target> | ||||
@@ -21,6 +21,7 @@ import org.apache.tools.ant.Task; | |||||
import org.apache.tools.ant.BuildException; | import org.apache.tools.ant.BuildException; | ||||
import org.apache.tools.ant.util.JavaEnvUtils; | import org.apache.tools.ant.util.JavaEnvUtils; | ||||
import org.apache.tools.ant.types.FileSet; | import org.apache.tools.ant.types.FileSet; | ||||
import org.apache.tools.ant.types.Path; | |||||
import org.apache.tools.ant.types.RedirectorElement; | import org.apache.tools.ant.types.RedirectorElement; | ||||
import org.apache.tools.ant.types.Environment; | import org.apache.tools.ant.types.Environment; | ||||
@@ -90,6 +91,13 @@ public abstract class AbstractJarSignerTask extends Task { | |||||
public static final String ERROR_NO_SOURCE = "jar must be set through jar attribute " | public static final String ERROR_NO_SOURCE = "jar must be set through jar attribute " | ||||
+ "or nested filesets"; | + "or nested filesets"; | ||||
/** | |||||
* Path holding all non-filesets of filesystem resources we want to sign. | |||||
* | |||||
* @since Ant 1.7 | |||||
*/ | |||||
private Path path = null; | |||||
/** | /** | ||||
* Set the maximum memory to be used by the jarsigner process | * Set the maximum memory to be used by the jarsigner process | ||||
* | * | ||||
@@ -181,6 +189,20 @@ public abstract class AbstractJarSignerTask extends Task { | |||||
public void addSysproperty(Environment.Variable sysp) { | public void addSysproperty(Environment.Variable sysp) { | ||||
sysProperties.addVariable(sysp); | sysProperties.addVariable(sysp); | ||||
} | } | ||||
/** | |||||
* Adds a path of files to sign. | |||||
* | |||||
* @param a path of files to sign. | |||||
* @since Ant 1.7 | |||||
*/ | |||||
public Path createPath() { | |||||
if (path == null) { | |||||
path = new Path(getProject()); | |||||
} | |||||
return path.createPath(); | |||||
} | |||||
/** | /** | ||||
* init processing logic; this is retained through our execution(s) | * init processing logic; this is retained through our execution(s) | ||||
*/ | */ | ||||
@@ -306,6 +328,7 @@ public abstract class AbstractJarSignerTask extends Task { | |||||
//this lets us combine our logic for handling output directories, | //this lets us combine our logic for handling output directories, | ||||
//mapping etc. | //mapping etc. | ||||
FileSet sourceJar = new FileSet(); | FileSet sourceJar = new FileSet(); | ||||
sourceJar.setProject(getProject()); | |||||
sourceJar.setFile(jar); | sourceJar.setFile(jar); | ||||
sourceJar.setDir(jar.getParentFile()); | sourceJar.setDir(jar.getParentFile()); | ||||
sources.add(sourceJar); | sources.add(sourceJar); | ||||
@@ -313,6 +336,31 @@ public abstract class AbstractJarSignerTask extends Task { | |||||
return sources; | return sources; | ||||
} | } | ||||
/** | |||||
* clone our path and add all explicitly specified FileSets as | |||||
* well, patch in the jar attribute as a new fileset if it is | |||||
* defined. | |||||
* @return a path that contains all files to sign | |||||
* @since Ant 1.7 | |||||
*/ | |||||
protected Path createUnifiedSourcePath() { | |||||
Path p = path == null ? new Path(getProject()) : (Path) path.clone(); | |||||
Vector s = createUnifiedSources(); | |||||
Enumeration e = s.elements(); | |||||
while (e.hasMoreElements()) { | |||||
p.add((FileSet) e.nextElement()); | |||||
} | |||||
return p; | |||||
} | |||||
/** | |||||
* Has either a path or a fileset been specified? | |||||
* @since Ant 1.7 | |||||
*/ | |||||
protected boolean hasResources() { | |||||
return path != null || filesets.size() > 0; | |||||
} | |||||
/** | /** | ||||
* add a value argument to a command | * add a value argument to a command | ||||
* @param cmd command to manipulate | * @param cmd command to manipulate | ||||
@@ -19,13 +19,14 @@ 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.Vector; | |||||
import java.util.Iterator; | |||||
import org.apache.tools.ant.BuildException; | import org.apache.tools.ant.BuildException; | ||||
import org.apache.tools.ant.DirectoryScanner; | import org.apache.tools.ant.DirectoryScanner; | ||||
import org.apache.tools.ant.Project; | import org.apache.tools.ant.Project; | ||||
import org.apache.tools.ant.taskdefs.condition.IsSigned; | import org.apache.tools.ant.taskdefs.condition.IsSigned; | ||||
import org.apache.tools.ant.types.FileSet; | |||||
import org.apache.tools.ant.types.Path; | |||||
import org.apache.tools.ant.types.resources.FileResource; | |||||
import org.apache.tools.ant.util.FileUtils; | import org.apache.tools.ant.util.FileUtils; | ||||
import org.apache.tools.ant.util.IdentityMapper; | import org.apache.tools.ant.util.IdentityMapper; | ||||
import org.apache.tools.ant.util.FileNameMapper; | import org.apache.tools.ant.util.FileNameMapper; | ||||
@@ -80,7 +81,7 @@ public class SignJar extends AbstractJarSignerTask { | |||||
protected boolean lazy; | protected boolean lazy; | ||||
/** | /** | ||||
* the output directory when using filesets. | |||||
* the output directory when using paths. | |||||
*/ | */ | ||||
protected File destDir; | protected File destDir; | ||||
@@ -111,7 +112,7 @@ public class SignJar extends AbstractJarSignerTask { | |||||
/** | /** | ||||
* error string for unit test verification {@value} | * error string for unit test verification {@value} | ||||
*/ | */ | ||||
public static final String ERROR_SIGNEDJAR_AND_FILESETS = "You cannot specify the signed JAR when using filesets"; | |||||
public static final String ERROR_SIGNEDJAR_AND_PATHS = "You cannot specify the signed JAR when using paths or filesets"; | |||||
/** | /** | ||||
* error string for unit test verification: {@value} | * error string for unit test verification: {@value} | ||||
*/ | */ | ||||
@@ -252,13 +253,12 @@ public class SignJar extends AbstractJarSignerTask { | |||||
*/ | */ | ||||
public void execute() throws BuildException { | public void execute() throws BuildException { | ||||
//validation logic | //validation logic | ||||
final boolean hasFileset = filesets.size() > 0; | |||||
final boolean hasJar = jar != null; | final boolean hasJar = jar != null; | ||||
final boolean hasSignedJar = signedjar != null; | final boolean hasSignedJar = signedjar != null; | ||||
final boolean hasDestDir = destDir != null; | final boolean hasDestDir = destDir != null; | ||||
final boolean hasMapper = mapper != null; | final boolean hasMapper = mapper != null; | ||||
if (!hasJar && !hasFileset) { | |||||
if (!hasJar && !hasResources()) { | |||||
throw new BuildException(ERROR_NO_SOURCE); | throw new BuildException(ERROR_NO_SOURCE); | ||||
} | } | ||||
if (null == alias) { | if (null == alias) { | ||||
@@ -274,8 +274,8 @@ public class SignJar extends AbstractJarSignerTask { | |||||
} | } | ||||
if (hasFileset && hasSignedJar) { | |||||
throw new BuildException(ERROR_SIGNEDJAR_AND_FILESETS); | |||||
if (hasResources() && hasSignedJar) { | |||||
throw new BuildException(ERROR_SIGNEDJAR_AND_PATHS); | |||||
} | } | ||||
//this isnt strictly needed, but by being fussy now, | //this isnt strictly needed, but by being fussy now, | ||||
@@ -297,9 +297,9 @@ public class SignJar extends AbstractJarSignerTask { | |||||
} | } | ||||
//the rest of the method treats single jar like | //the rest of the method treats single jar like | ||||
//a nested fileset with one file | |||||
//a nested path with one file | |||||
Vector sources = createUnifiedSources(); | |||||
Path sources = createUnifiedSourcePath(); | |||||
//set up our mapping policy | //set up our mapping policy | ||||
FileNameMapper destMapper; | FileNameMapper destMapper; | ||||
if (hasMapper) { | if (hasMapper) { | ||||
@@ -310,34 +310,26 @@ public class SignJar extends AbstractJarSignerTask { | |||||
} | } | ||||
//at this point the filesets are set up with lists of files, | |||||
//at this point the paths are set up with lists of files, | |||||
//and the mapper is ready to map from source dirs to dest files | //and the mapper is ready to map from source dirs to dest files | ||||
//now we iterate through every JAR giving source and dest names | //now we iterate through every JAR giving source and dest names | ||||
// deal with the filesets | |||||
for (int i = 0; i < sources.size(); i++) { | |||||
FileSet fs = (FileSet) sources.elementAt(i); | |||||
//get all included files in a fileset | |||||
DirectoryScanner ds = fs.getDirectoryScanner(getProject()); | |||||
String[] jarFiles = ds.getIncludedFiles(); | |||||
File baseDir = fs.getDir(getProject()); | |||||
// deal with the paths | |||||
Iterator iter = sources.iterator(); | |||||
while (iter.hasNext()) { | |||||
FileResource fr = (FileResource) iter.next(); | |||||
//calculate our destination directory; it is either the destDir | //calculate our destination directory; it is either the destDir | ||||
//attribute, or the base dir of the fileset (for in situ updates) | //attribute, or the base dir of the fileset (for in situ updates) | ||||
File toDir = hasDestDir ? destDir : baseDir; | |||||
//loop through all jars in the fileset | |||||
for (int j = 0; j < jarFiles.length; j++) { | |||||
String jarFile = jarFiles[j]; | |||||
//determine the destination filename via the mapper | |||||
String[] destFilenames = destMapper.mapFileName(jarFile); | |||||
if (destFilenames == null || destFilenames.length != 1) { | |||||
//we only like simple mappers. | |||||
throw new BuildException(ERROR_BAD_MAP + jarFile); | |||||
} | |||||
File destFile = new File(toDir, destFilenames[0]); | |||||
File jarSource = new File(baseDir, jarFile); | |||||
signOneJar(jarSource, destFile); | |||||
File toDir = hasDestDir ? destDir : fr.getBaseDir(); | |||||
//determine the destination filename via the mapper | |||||
String[] destFilenames = destMapper.mapFileName(fr.getName()); | |||||
if (destFilenames == null || destFilenames.length != 1) { | |||||
//we only like simple mappers. | |||||
throw new BuildException(ERROR_BAD_MAP + fr.getFile()); | |||||
} | } | ||||
File destFile = new File(toDir, destFilenames[0]); | |||||
signOneJar(fr.getFile(), destFile); | |||||
} | } | ||||
} finally { | } finally { | ||||
endExecution(); | endExecution(); | ||||
@@ -86,7 +86,21 @@ public class SignJarTest extends BuildFileTest { | |||||
public void testFilesetAndSignedJar() { | public void testFilesetAndSignedJar() { | ||||
expectBuildExceptionContaining("testFilesetAndSignedJar", | expectBuildExceptionContaining("testFilesetAndSignedJar", | ||||
"incompatible attributes", | "incompatible attributes", | ||||
SignJar.ERROR_SIGNEDJAR_AND_FILESETS); | |||||
SignJar.ERROR_SIGNEDJAR_AND_PATHS); | |||||
} | |||||
public void testPath() { | |||||
executeTarget("testPath"); | |||||
} | |||||
public void testPathAndJar() { | |||||
executeTarget("testPathAndJar"); | |||||
} | |||||
public void testPathAndSignedJar() { | |||||
expectBuildExceptionContaining("testPathAndSignedJar", | |||||
"incompatible attributes", | |||||
SignJar.ERROR_SIGNEDJAR_AND_PATHS); | |||||
} | } | ||||
public void testSignedJar() { | public void testSignedJar() { | ||||
@@ -100,7 +114,13 @@ public class SignJarTest extends BuildFileTest { | |||||
public void testDestDirAndSignedJar() { | public void testDestDirAndSignedJar() { | ||||
expectBuildExceptionContaining("testFilesetAndSignedJar", | expectBuildExceptionContaining("testFilesetAndSignedJar", | ||||
"incompatible attributes", | "incompatible attributes", | ||||
SignJar.ERROR_SIGNEDJAR_AND_FILESETS); | |||||
SignJar.ERROR_SIGNEDJAR_AND_PATHS); | |||||
} | |||||
public void testDestDirAndSignedJar2() { | |||||
expectBuildExceptionContaining("testPathAndSignedJar", | |||||
"incompatible attributes", | |||||
SignJar.ERROR_SIGNEDJAR_AND_PATHS); | |||||
} | } | ||||
public void testDestDirFileset() { | public void testDestDirFileset() { | ||||
@@ -111,6 +131,14 @@ public class SignJarTest extends BuildFileTest { | |||||
executeTarget("testMapperFileset"); | executeTarget("testMapperFileset"); | ||||
} | } | ||||
public void testDestDirPath() { | |||||
executeTarget("testDestDirPath"); | |||||
} | |||||
public void testMapperPath() { | |||||
executeTarget("testMapperPath"); | |||||
} | |||||
public void testMapperNoDest() { | public void testMapperNoDest() { | ||||
expectBuildExceptionContaining("testMapperNoDest", | expectBuildExceptionContaining("testMapperNoDest", | ||||
"two mappers", | "two mappers", | ||||
@@ -180,4 +208,8 @@ public class SignJarTest extends BuildFileTest { | |||||
executeTarget("testVerifyFileset"); | executeTarget("testVerifyFileset"); | ||||
} | } | ||||
public void testVerifyPath() { | |||||
executeTarget("testVerifyPath"); | |||||
} | |||||
} | } |