diff options
Diffstat (limited to 'framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/Cab.java')
-rw-r--r-- | framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/Cab.java | 357 |
1 files changed, 357 insertions, 0 deletions
diff --git a/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/Cab.java b/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/Cab.java new file mode 100644 index 00000000..11c091a8 --- /dev/null +++ b/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/Cab.java @@ -0,0 +1,357 @@ +/* + * 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.tools.ant.taskdefs.optional; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.OutputStream; +import java.util.Enumeration; +import java.util.Vector; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.DirectoryScanner; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.taskdefs.ExecTask; +import org.apache.tools.ant.taskdefs.Execute; +import org.apache.tools.ant.taskdefs.LogOutputStream; +import org.apache.tools.ant.taskdefs.MatchingTask; +import org.apache.tools.ant.taskdefs.StreamPumper; +import org.apache.tools.ant.taskdefs.condition.Os; +import org.apache.tools.ant.types.FileSet; +import org.apache.tools.ant.util.FileUtils; + + +/** + * Create a CAB archive. + * + */ + +public class Cab extends MatchingTask { + private static final int DEFAULT_RESULT = -99; + private File cabFile; + private File baseDir; + private Vector filesets = new Vector(); + private boolean doCompress = true; + private boolean doVerbose = false; + private String cmdOptions; + + // CheckStyle:VisibilityModifier OFF - bc + protected String archiveType = "cab"; + // CheckStyle:VisibilityModifier ON + + private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); + + /** + * The name/location of where to create the .cab file. + * @param cabFile the location of the cab file. + */ + public void setCabfile(File cabFile) { + this.cabFile = cabFile; + } + + /** + * Base directory to look in for files to CAB. + * @param baseDir base directory for files to cab. + */ + public void setBasedir(File baseDir) { + this.baseDir = baseDir; + } + + /** + * If true, compress the files otherwise only store them. + * @param compress a <code>boolean</code> value. + */ + public void setCompress(boolean compress) { + doCompress = compress; + } + + /** + * If true, display cabarc output. + * @param verbose a <code>boolean</code> value. + */ + public void setVerbose(boolean verbose) { + doVerbose = verbose; + } + + /** + * Sets additional cabarc options that are not supported directly. + * @param options cabarc command line options. + */ + public void setOptions(String options) { + cmdOptions = options; + } + + /** + * Adds a set of files to archive. + * @param set a set of files to archive. + */ + public void addFileset(FileSet set) { + if (filesets.size() > 0) { + throw new BuildException("Only one nested fileset allowed"); + } + filesets.addElement(set); + } + + /* + * I'm not fond of this pattern: "sub-method expected to throw + * task-cancelling exceptions". It feels too much like programming + * for side-effects to me... + */ + /** + * Check if the attributes and nested elements are correct. + * @throws BuildException on error. + */ + protected void checkConfiguration() throws BuildException { + if (baseDir == null && filesets.size() == 0) { + throw new BuildException("basedir attribute or one " + + "nested fileset is required!", + getLocation()); + } + if (baseDir != null && !baseDir.exists()) { + throw new BuildException("basedir does not exist!", getLocation()); + } + if (baseDir != null && filesets.size() > 0) { + throw new BuildException( + "Both basedir attribute and a nested fileset is not allowed"); + } + if (cabFile == null) { + throw new BuildException("cabfile attribute must be set!", + getLocation()); + } + } + + /** + * Create a new exec delegate. The delegate task is populated so that + * it appears in the logs to be the same task as this one. + * @return the delegate. + * @throws BuildException on error. + */ + protected ExecTask createExec() throws BuildException { + ExecTask exec = new ExecTask(this); + return exec; + } + + /** + * Check to see if the target is up to date with respect to input files. + * @param files the list of files to check. + * @return true if the cab file is newer than its dependents. + */ + protected boolean isUpToDate(Vector files) { + boolean upToDate = true; + final int size = files.size(); + for (int i = 0; i < size && upToDate; i++) { + String file = files.elementAt(i).toString(); + if (FILE_UTILS.resolveFile(baseDir, file).lastModified() + > cabFile.lastModified()) { + upToDate = false; + } + } + return upToDate; + } + + /** + * Creates a list file. This temporary file contains a list of all files + * to be included in the cab, one file per line. + * + * <p>This method expects to only be called on Windows and thus + * quotes the file names.</p> + * @param files the list of files to use. + * @return the list file created. + * @throws IOException if there is an error. + */ + protected File createListFile(Vector files) + throws IOException { + File listFile = FILE_UTILS.createTempFile("ant", "", null, true, true); + + BufferedWriter writer = null; + try { + writer = new BufferedWriter(new FileWriter(listFile)); + + final int size = files.size(); + for (int i = 0; i < size; i++) { + writer.write('\"' + files.elementAt(i).toString() + '\"'); + writer.newLine(); + } + } finally { + FileUtils.close(writer); + } + + return listFile; + } + + /** + * Append all files found by a directory scanner to a vector. + * @param files the vector to append the files to. + * @param ds the scanner to get the files from. + */ + protected void appendFiles(Vector files, DirectoryScanner ds) { + String[] dsfiles = ds.getIncludedFiles(); + + for (int i = 0; i < dsfiles.length; i++) { + files.addElement(dsfiles[i]); + } + } + + /** + * Get the complete list of files to be included in the cab. Filenames + * are gathered from the fileset if it has been added, otherwise from the + * traditional include parameters. + * @return the list of files. + * @throws BuildException if there is an error. + */ + protected Vector getFileList() throws BuildException { + Vector files = new Vector(); + + if (baseDir != null) { + // get files from old methods - includes and nested include + appendFiles(files, super.getDirectoryScanner(baseDir)); + } else { + FileSet fs = (FileSet) filesets.elementAt(0); + baseDir = fs.getDir(); + appendFiles(files, fs.getDirectoryScanner(getProject())); + } + + return files; + } + + /** + * execute this task. + * @throws BuildException on error. + */ + public void execute() throws BuildException { + + checkConfiguration(); + + Vector files = getFileList(); + + // quick exit if the target is up to date + if (isUpToDate(files)) { + return; + } + + log("Building " + archiveType + ": " + cabFile.getAbsolutePath()); + + if (!Os.isFamily("windows")) { + log("Using listcab/libcabinet", Project.MSG_VERBOSE); + + StringBuffer sb = new StringBuffer(); + + Enumeration fileEnum = files.elements(); + + while (fileEnum.hasMoreElements()) { + sb.append(fileEnum.nextElement()).append("\n"); + } + sb.append("\n").append(cabFile.getAbsolutePath()).append("\n"); + + try { + Process p = Execute.launch(getProject(), + new String[] {"listcab"}, null, + baseDir != null ? baseDir + : getProject().getBaseDir(), + true); + OutputStream out = p.getOutputStream(); + + // Create the stream pumpers to forward listcab's stdout and stderr to the log + // note: listcab is an interactive program, and issues prompts for every new line. + // Therefore, make it show only with verbose logging turned on. + LogOutputStream outLog = new LogOutputStream(this, Project.MSG_VERBOSE); + LogOutputStream errLog = new LogOutputStream(this, Project.MSG_ERR); + StreamPumper outPump = new StreamPumper(p.getInputStream(), outLog); + StreamPumper errPump = new StreamPumper(p.getErrorStream(), errLog); + + // Pump streams asynchronously + (new Thread(outPump)).start(); + (new Thread(errPump)).start(); + + out.write(sb.toString().getBytes()); + out.flush(); + out.close(); + + // A wild default for when the thread is interrupted + int result = DEFAULT_RESULT; + + try { + // Wait for the process to finish + result = p.waitFor(); + + // Wait for the end of output and error streams + outPump.waitFor(); + outLog.close(); + errPump.waitFor(); + errLog.close(); + } catch (InterruptedException ie) { + log("Thread interrupted: " + ie); + } + + // Informative summary message in case of errors + if (Execute.isFailure(result)) { + log("Error executing listcab; error code: " + result); + } + } catch (IOException ex) { + String msg = "Problem creating " + cabFile + " " + ex.getMessage(); + throw new BuildException(msg, getLocation()); + } + } else { + try { + File listFile = createListFile(files); + ExecTask exec = createExec(); + File outFile = null; + + // die if cabarc fails + exec.setFailonerror(true); + exec.setDir(baseDir); + + if (!doVerbose) { + outFile = FILE_UTILS.createTempFile("ant", "", null, true, true); + exec.setOutput(outFile); + } + + exec.setExecutable("cabarc"); + exec.createArg().setValue("-r"); + exec.createArg().setValue("-p"); + + if (!doCompress) { + exec.createArg().setValue("-m"); + exec.createArg().setValue("none"); + } + + if (cmdOptions != null) { + exec.createArg().setLine(cmdOptions); + } + + exec.createArg().setValue("n"); + exec.createArg().setFile(cabFile); + exec.createArg().setValue("@" + listFile.getAbsolutePath()); + + exec.execute(); + + if (outFile != null) { + outFile.delete(); + } + + listFile.delete(); + } catch (IOException ioe) { + String msg = "Problem creating " + cabFile + " " + ioe.getMessage(); + throw new BuildException(msg, getLocation()); + } + } + } +} |