blob: 69a8feb9702df77a675ddda1bce258cc8a8af2a3 [file] [log] [blame]
/*
* Copyright 2004 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.
*
*/
package org.apache.tools.ant.taskdefs.optional.dotnet;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.EnumeratedAttribute;
import org.apache.tools.ant.types.FileSet;
import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* Task to run the WiX utility to create MSI files from an XML description.
*
* @see http://sf.net/projects/wix
*/
public class WixTask extends Task {
/**
* The vm attribute - if given.
*/
private String vm;
/**
* The source files.
*/
private ArrayList sources = new ArrayList();
/**
* Additional source files (include files in the case of candle,
* or media/files/whatever in the case of light).
*/
private ArrayList moreSources = new ArrayList();
/**
* A single source file.
*/
private File source;
/**
* The target file.
*/
private File target;
/**
* What to do.
*/
private Mode mode;
public WixTask() {
super();
}
/**
* Set the name of the executable for the virtual machine.
*
* @param value the name of the executable for the virtual machine
*/
public void setVm(String value) {
this.vm = value;
}
/**
* The main source file.
*
* <p><code>candle</code> may include more files than this one,
* the main source is the one passed on the command line.</p>
*
* @param File object of the main source file.
*/
public void setSource(File f) {
source = f;
}
/**
* A set of source files.
*/
public void addSources(FileSet fs) {
sources.add(fs);
}
/**
* A set of additional source files (include files in the case of
* candle, or media/files/whatever in the case of light).
*
* <p>Unlike the files specified as sources, these will not be
* passed on the command line, they only help Ant to determine
* whether the target is out-of-date.</p>
*/
public void addMoreSources(FileSet fs) {
moreSources.add(fs);
}
public void execute() {
if (source == null && sources.size() == 0) {
throw new BuildException("You must specify at least one source"
+ " file.");
}
String m = Mode.BOTH;
if (mode != null) {
m = mode.getValue();
}
if (target == null && !m.equals(Mode.CANDLE)) {
throw new BuildException("You must specify the target if you want"
+ " to run light.");
}
List lightSources = new ArrayList();
if (!m.equals(Mode.LIGHT)) {
doCandle(lightSources);
} else {
if (source != null) {
lightSources.add(source);
}
if (sources.size() > 0) {
lightSources.addAll(grabFiles(sources));
}
}
List moreLightSources = new ArrayList();
if (moreSources.size() > 0) {
moreLightSources = grabFiles(moreSources);
}
if (!m.equals(Mode.CANDLE)) {
doLight(lightSources, moreLightSources);
}
}
/**
* Invoke candle on all sources that are newer than their targets.
*
* @param lightSources list that will be filled with File objects
* pointing to the generated object files.
*/
private void doCandle(List lightSources) {
List s = new ArrayList();
if (source != null) {
s.add(source);
}
if (sources != null) {
s.addAll(grabFiles(sources));
}
List ms = new ArrayList();
if (moreSources != null) {
ms.addAll(grabFiles(moreSources));
}
Iterator iter = s.iterator();
List toProcess = new ArrayList();
while (iter.hasNext()) {
File thisSource = (File) iter.next();
File t = target;
if (t == null) {
t = getTarget(thisSource);
}
if (isOutOfDate(t, thisSource, ms)) {
toProcess.add(thisSource);
lightSources.add(t);
}
}
if (toProcess.size() != 0) {
runCandle(toProcess);
}
}
/**
* Invoke light on all sources that are newer than their targets.
*/
private void doLight(List lightSources, List moreLightSources) {
List tmp = new ArrayList(lightSources);
tmp.addAll(moreLightSources);
if (isOutOfDate(target, tmp)) {
runLight(lightSources);
}
}
/**
* Run candle passing all files in list on the command line.
*/
private void runCandle(List s) {
run("candle.exe", s, null);
}
/**
* Run light passing all files in list on the command line.
*/
private void runLight(List s) {
run("light.exe", s, target);
}
/**
* Runs the specified command passing list on the command line an
* potentially adding an /out parameter.
*/
private void run(String executable, List s, File target) {
DotNetExecTask exec = DotNetExecTask.getTask(this, vm,
executable, null);
Iterator iter = s.iterator();
while (iter.hasNext()) {
File f = (File) iter.next();
exec.createArg().setValue(f.getAbsolutePath());
}
if (target != null) {
exec.createArg().setValue("/out");
exec.createArg().setValue(target.getAbsolutePath());
}
exec.execute();
}
/**
* Is t older than s or any of the files in list?
*/
private boolean isOutOfDate(File t, File s, List l) {
return t.lastModified() < s.lastModified() || isOutOfDate(t, l);
}
/**
* Is t older than any of the files in list?
*/
private boolean isOutOfDate(File t, List l) {
Iterator iter = l.iterator();
while (iter.hasNext()) {
File f = (File) iter.next();
if (t.lastModified() < f.lastModified()) {
return true;
}
}
return false;
}
/**
* Turn the fileset collection into a list of Files.
*/
private List grabFiles(List s) {
List r = new ArrayList();
Iterator iter = s.iterator();
while (iter.hasNext()) {
FileSet fs = (FileSet) iter.next();
DirectoryScanner ds = fs.getDirectoryScanner(getProject());
String[] f = ds.getIncludedFiles();
File base = fs.getDir(getProject());
for (int i = 0; i < f.length; i++) {
r.add(new File(base, f[i]));
}
}
return r;
}
/**
* Generates the name of a candle target from the source file.
*
* <p>Simply chops of the extension and adds .wixobj.</p>
*/
private File getTarget(File s) {
String name = s.getAbsolutePath();
int dot = name.lastIndexOf(".");
if (dot > -1) {
return new File(name.substring(0, dot) + ".wixobj");
} else {
return new File(name + ".wixobj");
}
}
public static class Mode extends EnumeratedAttribute {
private final static String CANDLE = "candle";
private final static String LIGHT = "light";
private final static String BOTH = "both";
public Mode() {
super();
}
public String[] getValues() {
return new String[] {CANDLE, LIGHT, BOTH,};
}
}
}