Attached is a CAB task I wrote some weeks ago to create Microsoft .cab
files. I know, I know, boo, hiss, but I had no choice - really. I have
to create these for one of my current projects, so I put this together.
The task syntax is just like jar or zip, since it really does the same
thing anyway.
Use it like this:
<cab cabfile="filename" basedir="dir"/>
All of the optional parameters from MatchingTask are supported
(including the nested params):
includes
excludes
items
ignore
defaultexcludes
This task contains OS checks and will only run on Windoze. It is
harmlessly ignored on other OSes. You must have the Microsoft CABARC
utility available in your executable path. I have not been able to find
any Java classes for creating CAB files - if anyone knows of any, please
let me know.
I'm donating the source to the project - you will see that I borrowed
heavily from existing tasks anyway.
Roger Vaughn
package org.apache.tools.ant.taskdefs.optional;
import org.apache.tools.ant.*;
import org.apache.tools.ant.taskdefs.*;
import java.io.*;
import java.util.Enumeration;
import java.util.StringTokenizer;
import java.util.Vector;
/**
* Create a CAB archive.
*
* @author Roger Vaughn <a href="mailto:[EMAIL PROTECTED]">[EMAIL PROTECTED]</a>
*/
public class Cab extends MatchingTask {
private File cabFile;
private File baseDir;
protected String archiveType = "cab";
/**
* This is the name/location of where to
* create the .cab file.
*/
public void setCabfile(String cabFilename) {
cabFile = project.resolveFile(cabFilename);
}
/**
* This is the base directory to look in for
* things to cab.
*/
public void setBasedir(String baseDirname) {
baseDir = project.resolveFile(baseDirname);
}
public void execute() throws BuildException {
String myos = System.getProperty("os.name");
log("Myos = " + myos, Project.MSG_VERBOSE);
if (myos.toLowerCase().indexOf("windows") < 0){
// this command will be executed only on the specified OS
log("Can only run cab tasks on Windows", Project.MSG_VERBOSE);
return;
}
if (baseDir == null) {
throw new BuildException("basedir attribute must be set!");
}
if (!baseDir.exists()) {
throw new BuildException("basedir does not exist!");
}
DirectoryScanner ds = super.getDirectoryScanner(baseDir);
String[] files = ds.getIncludedFiles();
String[] dirs = ds.getIncludedDirectories();
// quick exit if the target is up to date
boolean upToDate = true;
for (int i=0; i<files.length && upToDate; i++)
if (new File(baseDir,files[i]).lastModified() >
cabFile.lastModified())
upToDate = false;
if (upToDate) return;
log("Building "+ archiveType +": "+ cabFile.getAbsolutePath());
try {
File listFile = createListFile(files);
try
{
createCabFile(
baseDir.getAbsolutePath(),
cabFile.getAbsolutePath(),
listFile.getAbsolutePath());
}
finally
{
listFile.delete();
}
} catch (IOException ioe) {
String msg = "Problem creating " + archiveType + " " +
ioe.getMessage();
throw new BuildException(msg);
}
}
protected File createListFile(String[] files)
throws IOException
{
File listFile = File.createTempFile("ant", null);
PrintWriter writer = new PrintWriter(new FileOutputStream(listFile));
for (int i = 0; i < files.length; i++)
{
writer.println(files[i]);
}
writer.close();
return listFile;
}
protected void createCabFile(String dir, String cabFile, String listFile)
throws IOException
{
int err = -1; // assume the worst
String command =
"cmd /c cd " + project.resolveFile(dir) + " && " +
"cabarc -r -p n " + cabFile + " @" + listFile;
try {
// show the command
log(command, Project.MSG_VERBOSE);
// exec command on system runtime
Process proc = Runtime.getRuntime().exec(command);
// copy input and error to the output stream
StreamPumper inputPumper =
new StreamPumper(proc.getInputStream(), "exec", project, null);
StreamPumper errorPumper =
new StreamPumper(proc.getErrorStream(), "error", project, null);
// starts pumping away the generated output/error
inputPumper.start();
errorPumper.start();
// Wait for everything to finish
proc.waitFor();
inputPumper.join();
errorPumper.join();
proc.destroy();
// check its exit value
err = proc.exitValue();
if (err != 0) {
log("Result: " + err, Project.MSG_ERR);
}
} catch (InterruptedException ex) {}
}
// Inner class for continually pumping the input stream during
// Process's runtime.
class StreamPumper extends Thread {
private BufferedReader din;
private String name;
private boolean endOfStream = false;
private int SLEEP_TIME = 5;
private Project project;
private PrintWriter fos;
private static final int BUFFER_SIZE = 512;
public StreamPumper(InputStream is, String name, Project project,
PrintWriter fos) {
this.din = new BufferedReader(new InputStreamReader(is));
this.name = name;
this.project = project;
this.fos = fos;
}
public void pumpStream()
throws IOException
{
byte[] buf = new byte[BUFFER_SIZE];
if (!endOfStream) {
String line = din.readLine();
if (line != null) {
if (fos == null)
log(line, Project.MSG_INFO);
else
fos.println(line);
} else {
endOfStream = true;
}
}
}
public void run() {
try {
try {
while (!endOfStream) {
pumpStream();
sleep(SLEEP_TIME);
}
} catch (InterruptedException ie) {}
din.close();
} catch (IOException ioe) {}
}
}
}