Package org.apache.ant.dotnet.wix

Source Code of org.apache.ant.dotnet.wix.WixTask

/*
*  Licensed to the Apache Software Foundation (ASF) under one or more
*  contributor license agreements.  See the NOTICE file distributed with
*  this work for additional information regarding copyright ownership.
*  The ASF licenses this file to You 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.ant.dotnet.wix;

import org.apache.ant.dotnet.DotNetExecTask;
import org.apache.ant.dotnet.build.AbstractBuildTask;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.Commandline;
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.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

/**
* 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;

    /**
     * Where is WiX installed?
     */
    private File wixHome = null;

    /**
     * Where to place the generated .wixobj files.
     */
    private File wixobjDestDir = null;

    /**
     * addtional command line arguments for candle.
     */
    private Commandline candleCmdl = new Commandline();

    /**
     * list of parameters for the preprocessor.
     */
    private ArrayList candleParameters = new ArrayList();

    /**
     * addtional command line arguments for light.
     */
    private Commandline lightCmdl = new Commandline();

    /**
     * list of parameters for the "compiler".
     */
    private ArrayList lightParameters = new ArrayList();

    /**
     * Whether to use lit.exe rather than light.exe.
     */
    private boolean useLit = false;

    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;
    }

    /**
     * The main target file.
     *
     * @param File object of the main target file.
     */
    public void setTarget(File f) {
        target = 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);
    }

    /**
     * Sets the installation directory of WiX.
     *
     * <p>If omitted, Ant will assume that WiX's executables can be
     * found on the PATH.</p>
     */
    public void setWixHome(File f) {
        wixHome = f;
    }

    /**
     * Whether to run candle, light or both.
     */
    public void setMode(Mode m) {
        mode = m;
    }

    /**
     * Sets the destination directory for wixobj files generated by candle.
     *
     * <p>Let's candle decide and assumes they'll be created in the
     * current working directory.</p>
     */
    public void setWixobjDestDir(File f) {
        wixobjDestDir = f;
    }

    /**
     * A parameter to pass to candle.exe.
     */
    public final void addCandleParameter(AbstractBuildTask.Property t) {
        candleParameters.add(t);
    }

    /**
     * A parameter to pass to light.exe.
     */
    public final void addLightParameter(AbstractBuildTask.Property t) {
        lightParameters.add(t);
    }

    /**
     * Adds a command-line argument for light.exe.
     *
     * @return new command line argument created.
     */
    public Commandline.Argument createLightArg() {
        return lightCmdl.createArgument();
    }

    /**
     * Adds a command-line argument for candle.exe.
     *
     * @return new command line argument created.
     */
    public Commandline.Argument createCandleArg() {
        return candleCmdl.createArgument();
    }

    /**
     * Instructs the task to use lit.exe rather than light.exe as "compiler".
     *
     * @since .NET Antlib 1.1
     */
    public void setUseLit(boolean b) {
        useLit = b;
    }

    public void execute() {
        if (source == null && sources.size() == 0) {
            throw new BuildException("You must specify at least one source"
                                     + " file.");
        }

        if (source != null && !source.exists()) {
            throw new BuildException("Source file " + source
                                     + " doesn't exist.");
        }

        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.");
        }

        Collection lightSources = null;
        if (!m.equals(Mode.LIGHT)) {
            lightSources = doCandle();
        } else {
            lightSources = new HashSet();
            if (source != null) {
                lightSources.add(source);
            }
            if (sources.size() > 0) {
                lightSources.addAll(grabFiles(sources));
            }
        }

        if (!m.equals(Mode.CANDLE)) {
            Collection moreLightSources = Collections.EMPTY_SET;
            if (moreSources.size() > 0) {
                moreLightSources = grabFiles(moreSources);
            }
            doLight(lightSources, moreLightSources);
        }
    }

    /**
     * Invoke candle on all sources that are newer than their targets.
     *
     * @return a set of File objects pointing to the generated files.
     */
    private Collection doCandle() {
        Set s = new HashSet();
        if (source != null) {
            s.add(source);
        }
        if (sources != null) {
            s.addAll(grabFiles(sources));
        }
        Set ms = new HashSet();
        if (moreSources != null) {
            ms.addAll(grabFiles(moreSources));
        }

        Set toProcess = new HashSet();
        Set generatedTargets = new HashSet();
        Iterator iter = s.iterator();
        while (iter.hasNext()) {
            File thisSource = (File) iter.next();
            File t = getTarget(thisSource);
            generatedTargets.add(t);
            if (isOutOfDate(t, thisSource, ms)) {
                toProcess.add(thisSource);
            }
        }
        if (toProcess.size() != 0) {
            runCandle(toProcess);
            return generatedTargets;
        }
        return Collections.EMPTY_SET;
    }

    /**
     * Invoke light on all sources that are newer than their targets.
     */
    private void doLight(Collection lightSources,
                         Collection moreLightSources) {
        Set tmp = new HashSet(lightSources);
        tmp.addAll(moreLightSources);
        if (isOutOfDate(target, tmp)) {
            runLight(lightSources);
        }
    }

    /**
     * Run candle passing all files of the collection on the command line.
     */
    private void runCandle(Collection s) {
        run(wixExecutable("candle.exe"), s, null, wixobjDestDir,
            candleParameters, candleCmdl);
    }

    /**
     * Run light passing all files of the collection on the command line.
     */
    private void runLight(Collection s) {
        run(wixExecutable(useLit ? "lit.exe" : "light.exe"), s, target, null,
            lightParameters, lightCmdl);
    }

    /**
     * returns an absolute path for the given executable if wixHome
     * has been specified, the given name otherwise.
     */
    private String wixExecutable(String name) {
        return wixHome == null ? name
            : new File(wixHome, name).getAbsolutePath();
    }

    /**
     * Runs the specified command passing all files of the collection
     * on the command line - potentially adding an /out parameter.
     */
    private void run(String executable, Collection s, File target,
                     File runInDir, Collection params, Commandline cmdl) {
        DotNetExecTask exec = DotNetExecTask.getTask(this, vm,
                                                     executable, null);
        if (runInDir != null) {
            exec.setDir(runInDir);
        }

        exec.setFailonerror(true);
        exec.setTaskType("wix");

        exec.createArg().setValue("/nologo");

        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());
        }

        iter = params.iterator();
        while (iter.hasNext()) {
            AbstractBuildTask.Property p =
                (AbstractBuildTask.Property) iter.next();
            exec.createArg().setValue("-d" + p.getName() + "=" + p.getValue());
        }
        String[] extraArgs = cmdl.getArguments();
        for (int i = 0; i < extraArgs.length; i++) {
            exec.createArg().setValue(extraArgs[i]);
        }

        exec.execute();
    }

    /**
     * Is t older than s or any of the files in list?
     */
    private boolean isOutOfDate(File t, File s, Collection l) {
        return t.lastModified() < s.lastModified() || isOutOfDate(t, l);
    }

    /**
     * Is t older than any of the files in list?
     */
    private boolean isOutOfDate(File t, Collection 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 Collection grabFiles(Collection s) {
        Set r = new HashSet();
        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, adds .wixobj and calculates
     * the absolute path based on wixobjDestDir.</p>
     */
    private File getTarget(File s) {
        String name = s.getName();
        int dot = name.lastIndexOf(".");
        if (dot > -1) {
            name = name.substring(0, dot) + ".wixobj";
        } else {
            name = name + ".wixobj";
        }

        return wixobjDestDir == null
            ? new File(name) : new File(wixobjDestDir, name);
    }

    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,};
        }
    }
}
TOP

Related Classes of org.apache.ant.dotnet.wix.WixTask

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.