source: release-kits/lirk3/resources/gs3-release-maker/apache-ant-1.6.5/src/main/org/apache/tools/ant/taskdefs/optional/Cab.java@ 14982

Last change on this file since 14982 was 14982, checked in by oranfry, 16 years ago

initial import of LiRK3

File size: 10.9 KB
Line 
1/*
2 * Copyright 2000-2005 The Apache Software Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17
18package org.apache.tools.ant.taskdefs.optional;
19
20import java.io.File;
21import java.io.FileOutputStream;
22import java.io.IOException;
23import java.io.OutputStream;
24import java.io.PrintWriter;
25import java.util.Enumeration;
26import java.util.Vector;
27import org.apache.tools.ant.BuildException;
28import org.apache.tools.ant.DirectoryScanner;
29import org.apache.tools.ant.Project;
30import org.apache.tools.ant.taskdefs.ExecTask;
31import org.apache.tools.ant.taskdefs.Execute;
32import org.apache.tools.ant.taskdefs.LogOutputStream;
33import org.apache.tools.ant.taskdefs.MatchingTask;
34import org.apache.tools.ant.taskdefs.StreamPumper;
35import org.apache.tools.ant.taskdefs.condition.Os;
36import org.apache.tools.ant.types.FileSet;
37import org.apache.tools.ant.util.FileUtils;
38
39
40/**
41 * Create a CAB archive.
42 *
43 */
44
45public class Cab extends MatchingTask {
46
47 private File cabFile;
48 private File baseDir;
49 private Vector filesets = new Vector();
50 private boolean doCompress = true;
51 private boolean doVerbose = false;
52 private String cmdOptions;
53
54 protected String archiveType = "cab";
55
56 private FileUtils fileUtils = FileUtils.newFileUtils();
57
58 /**
59 * The name/location of where to create the .cab file.
60 */
61 public void setCabfile(File cabFile) {
62 this.cabFile = cabFile;
63 }
64
65 /**
66 * Base directory to look in for files to CAB.
67 */
68 public void setBasedir(File baseDir) {
69 this.baseDir = baseDir;
70 }
71
72 /**
73 * If true, compress the files otherwise only store them.
74 */
75 public void setCompress(boolean compress) {
76 doCompress = compress;
77 }
78
79 /**
80 * If true, display cabarc output.
81 */
82 public void setVerbose(boolean verbose) {
83 doVerbose = verbose;
84 }
85
86 /**
87 * Sets additional cabarc options that are not supported directly.
88 */
89 public void setOptions(String options) {
90 cmdOptions = options;
91 }
92
93 /**
94 * Adds a set of files to archive.
95 */
96 public void addFileset(FileSet set) {
97 filesets.addElement(set);
98 }
99
100 /*
101 * I'm not fond of this pattern: "sub-method expected to throw
102 * task-cancelling exceptions". It feels too much like programming
103 * for side-effects to me...
104 */
105 protected void checkConfiguration() throws BuildException {
106 if (baseDir == null && filesets.size() == 0) {
107 throw new BuildException("basedir attribute or at least one "
108 + "nested filest is required!",
109 getLocation());
110 }
111 if (baseDir != null && !baseDir.exists()) {
112 throw new BuildException("basedir does not exist!", getLocation());
113 }
114 if (cabFile == null) {
115 throw new BuildException("cabfile attribute must be set!",
116 getLocation());
117 }
118 }
119
120 /**
121 * Create a new exec delegate. The delegate task is populated so that
122 * it appears in the logs to be the same task as this one.
123 */
124 protected ExecTask createExec() throws BuildException {
125 ExecTask exec = (ExecTask) getProject().createTask("exec");
126 exec.setOwningTarget(this.getOwningTarget());
127 exec.setTaskName(this.getTaskName());
128 exec.setDescription(this.getDescription());
129
130 return exec;
131 }
132
133 /**
134 * Check to see if the target is up to date with respect to input files.
135 * @return true if the cab file is newer than its dependents.
136 */
137 protected boolean isUpToDate(Vector files) {
138 boolean upToDate = true;
139 for (int i = 0; i < files.size() && upToDate; i++) {
140 String file = files.elementAt(i).toString();
141 if (fileUtils.resolveFile(baseDir, file).lastModified()
142 > cabFile.lastModified()) {
143 upToDate = false;
144 }
145 }
146 return upToDate;
147 }
148
149 /**
150 * Creates a list file. This temporary file contains a list of all files
151 * to be included in the cab, one file per line.
152 *
153 * <p>This method expects to only be called on Windows and thus
154 * quotes the file names.</p>
155 */
156 protected File createListFile(Vector files)
157 throws IOException {
158 File listFile = fileUtils.createTempFile("ant", "", null);
159 listFile.deleteOnExit();
160
161 PrintWriter writer = new PrintWriter(new FileOutputStream(listFile));
162
163 int size = files.size();
164 for (int i = 0; i < size; i++) {
165 writer.println('\"' + files.elementAt(i).toString() + '\"');
166 }
167 writer.close();
168
169 return listFile;
170 }
171
172 /**
173 * Append all files found by a directory scanner to a vector.
174 */
175 protected void appendFiles(Vector files, DirectoryScanner ds) {
176 String[] dsfiles = ds.getIncludedFiles();
177
178 for (int i = 0; i < dsfiles.length; i++) {
179 files.addElement(dsfiles[i]);
180 }
181 }
182
183 /**
184 * Get the complete list of files to be included in the cab. Filenames
185 * are gathered from filesets if any have been added, otherwise from the
186 * traditional include parameters.
187 */
188 protected Vector getFileList() throws BuildException {
189 Vector files = new Vector();
190
191 if (baseDir != null) {
192 // get files from old methods - includes and nested include
193 appendFiles(files, super.getDirectoryScanner(baseDir));
194 }
195
196 // get files from filesets
197 for (int i = 0; i < filesets.size(); i++) {
198 FileSet fs = (FileSet) filesets.elementAt(i);
199 if (fs != null) {
200 appendFiles(files, fs.getDirectoryScanner(getProject()));
201 }
202 }
203
204 return files;
205 }
206
207 public void execute() throws BuildException {
208
209 checkConfiguration();
210
211 Vector files = getFileList();
212
213 // quick exit if the target is up to date
214 if (isUpToDate(files)) {
215 return;
216 }
217
218 log("Building " + archiveType + ": " + cabFile.getAbsolutePath());
219
220 if (!Os.isFamily("windows")) {
221 log("Using listcab/libcabinet", Project.MSG_VERBOSE);
222
223 StringBuffer sb = new StringBuffer();
224
225 Enumeration fileEnum = files.elements();
226
227 while (fileEnum.hasMoreElements()) {
228 sb.append(fileEnum.nextElement()).append("\n");
229 }
230 sb.append("\n").append(cabFile.getAbsolutePath()).append("\n");
231
232 try {
233 Process p = Execute.launch(getProject(),
234 new String[] {"listcab"}, null,
235 baseDir != null ? baseDir
236 : getProject().getBaseDir(),
237 true);
238 OutputStream out = p.getOutputStream();
239
240 // Create the stream pumpers to forward listcab's stdout and stderr to the log
241 // note: listcab is an interactive program, and issues prompts for every new line.
242 // Therefore, make it show only with verbose logging turned on.
243 LogOutputStream outLog = new LogOutputStream(this, Project.MSG_VERBOSE);
244 LogOutputStream errLog = new LogOutputStream(this, Project.MSG_ERR);
245 StreamPumper outPump = new StreamPumper(p.getInputStream(), outLog);
246 StreamPumper errPump = new StreamPumper(p.getErrorStream(), errLog);
247
248 // Pump streams asynchronously
249 (new Thread(outPump)).start();
250 (new Thread(errPump)).start();
251
252 out.write(sb.toString().getBytes());
253 out.flush();
254 out.close();
255
256 int result = -99; // A wild default for when the thread is interrupted
257
258 try {
259 // Wait for the process to finish
260 result = p.waitFor();
261
262 // Wait for the end of output and error streams
263 outPump.waitFor();
264 outLog.close();
265 errPump.waitFor();
266 errLog.close();
267 } catch (InterruptedException ie) {
268 log("Thread interrupted: " + ie);
269 }
270
271 // Informative summary message in case of errors
272 if (Execute.isFailure(result)) {
273 log("Error executing listcab; error code: " + result);
274 }
275 } catch (IOException ex) {
276 String msg = "Problem creating " + cabFile + " " + ex.getMessage();
277 throw new BuildException(msg, getLocation());
278 }
279 } else {
280 try {
281 File listFile = createListFile(files);
282 ExecTask exec = createExec();
283 File outFile = null;
284
285 // die if cabarc fails
286 exec.setFailonerror(true);
287 exec.setDir(baseDir);
288
289 if (!doVerbose) {
290 outFile = fileUtils.createTempFile("ant", "", null);
291 outFile.deleteOnExit();
292 exec.setOutput(outFile);
293 }
294
295 exec.setExecutable("cabarc");
296 exec.createArg().setValue("-r");
297 exec.createArg().setValue("-p");
298
299 if (!doCompress) {
300 exec.createArg().setValue("-m");
301 exec.createArg().setValue("none");
302 }
303
304 if (cmdOptions != null) {
305 exec.createArg().setLine(cmdOptions);
306 }
307
308 exec.createArg().setValue("n");
309 exec.createArg().setFile(cabFile);
310 exec.createArg().setValue("@" + listFile.getAbsolutePath());
311
312 exec.execute();
313
314 if (outFile != null) {
315 outFile.delete();
316 }
317
318 listFile.delete();
319 } catch (IOException ioe) {
320 String msg = "Problem creating " + cabFile + " " + ioe.getMessage();
321 throw new BuildException(msg, getLocation());
322 }
323 }
324 }
325}
Note: See TracBrowser for help on using the repository browser.