1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package installtoolkit.wix;
19
20 import java.io.File;
21 import java.io.FileWriter;
22 import java.io.IOException;
23 import java.util.ArrayList;
24 import java.util.List;
25 import java.util.UUID;
26
27 import org.apache.tools.ant.BuildException;
28 import org.apache.tools.ant.Task;
29 import org.apache.tools.ant.types.Path;
30 import org.dom4j.Document;
31 import org.dom4j.DocumentHelper;
32 import org.dom4j.Element;
33 import org.dom4j.io.OutputFormat;
34 import org.dom4j.io.XMLWriter;
35
36 /**
37 * Task to generate a WiX fragment file containing a file hierachie
38 * build from a directory structure.
39 *
40 * @author Christian Elberfeld <elberfeld@web.de>
41 */
42 public class FilesFragmentGeneratorTask extends Task {
43
44 private boolean debug = false;
45 private String fragmentid;
46 private String directoryid;
47 private String featureid;
48 private File destdir;
49 private String filename = "FilesFragment.wxs";
50 private String idprefix = "";
51 private File srcdir;
52 private String diskid = "1";
53 private String startmenuefolder;
54
55 private Path configfiles;
56 private List<Shortcut> desktopshortcuts = new ArrayList<Shortcut>();
57 private List<Shortcut> startmenueshortcuts = new ArrayList<Shortcut>();
58
59 private IdGenarator idgen;
60 private FilenameGenarator namegen;
61 private List<File> configs;
62 private Document document;
63 private Element fragment;
64 private Element feature;
65
66
67 /**
68 * @see Task#execute()
69 */
70 @Override
71 public void execute() throws BuildException {
72
73 try {
74
75 if (debug) handleOutput("starting execute()");
76
77 if (this.fragmentid == null) throw new BuildException("Attribute \"fragmentid\" must be set");
78 if (this.directoryid == null) throw new BuildException("Attribute \"directoryid\" must be set");
79 if (this.featureid == null) throw new BuildException("Attribute \"featureid\" must be set");
80 if (this.destdir == null) throw new BuildException("Attribute \"destdir\" must be set");
81 if (this.srcdir == null) throw new BuildException("Attribute \"srcdir\" must be set");
82
83 this.idgen = new IdGenarator(10,this.idprefix);
84 this.namegen = new FilenameGenarator();
85
86 this.configs = new ArrayList<File>();
87
88 if (this.configfiles != null) {
89
90 String[] configfiles_list = this.configfiles.list();
91 if (debug) handleOutput("Number of Configfiles: "+configfiles_list.length);
92
93 for (String name : configfiles_list) {
94
95 File f = this.getProject().resolveFile(name);
96 configs.add(f);
97 if (debug) handleOutput("Config File: "+f.getAbsolutePath());
98
99 }
100
101 } else {
102
103 if (debug) handleOutput("No Config Files ... ");
104 }
105
106
107 this.document = DocumentHelper.createDocument();
108 Element wix = document.addElement( "Wix" , "http://schemas.microsoft.com/wix/2003/01/wi");
109
110 this.fragment = wix.addElement("Fragment");
111 fragment.addAttribute("Id",this.fragmentid);
112
113 Element dir = fragment.addElement("DirectoryRef");
114 dir.addAttribute("Id",this.directoryid);
115
116 Element desktop = dir.addElement("Directory");
117 desktop.addAttribute("Id",this.idprefix + "DesktopFolder");
118 desktop.addAttribute("Name","Desktop");
119
120 Element startmenue = dir.addElement("Directory");
121 startmenue.addAttribute("Id",this.idprefix + "ProgramMenuFolder");
122 startmenue.addAttribute("Name","PMenu");
123
124 if (startmenuefolder != null) {
125
126 Element startmenue_dir = startmenue.addElement("Directory");
127 startmenue_dir.addAttribute("Id",this.idprefix + "Start_Menue_Folder");
128
129 if (this.startmenuefolder.length() > 8) {
130
131 startmenue_dir.addAttribute("LongName",this.startmenuefolder);
132 startmenue_dir.addAttribute("Name",this.startmenuefolder.substring(0,7).replace(" ","_"));
133
134 } else {
135
136 startmenue_dir.addAttribute("Name",this.startmenuefolder.replace(" ","_"));
137 }
138
139 }
140
141 this.feature = fragment.addElement("FeatureRef");
142 feature.addAttribute("Id",this.featureid);
143
144 proceedDirectory(dir,this.srcdir);
145
146 File destfile = new File(this.destdir,this.filename);
147
148 handleOutput("Writing: "+destfile.getName());
149 if (this.debug) handleOutput("File: "+destfile.getAbsolutePath());
150
151 if (destfile.exists()) destfile.delete();
152
153 OutputFormat format = OutputFormat.createPrettyPrint();
154 XMLWriter writer = new XMLWriter( new FileWriter( destfile ), format );
155 writer.write( document );
156 writer.close();
157
158 if (debug) handleOutput("execute() finished");
159
160 } catch (IOException e) {
161
162 throw new BuildException(e.getMessage(),e);
163 }
164
165 }
166
167 /**
168 * Function to proceed a directory. <br/>
169 * This Function operates recursively on a directory structure.
170 *
171 * @param dir_elem The current <Directory> element of the fragmnet file
172 * @param dir The current directory
173 */
174 private void proceedDirectory(Element dir_elem, File dir) {
175
176 if (debug) handleOutput("Dir: "+dir.getAbsolutePath());
177
178 for (File f : dir.listFiles()) {
179
180 if (f.isFile()) {
181
182 boolean config = configs.contains(f);
183 String compid = ('C' + idgen.next());
184
185 if (debug) handleOutput("File [Config: "+config+"]: "+f.getAbsolutePath()+" Id: "+compid);
186
187
188 Element comp_elem = dir_elem.addElement("Component");
189 comp_elem.addAttribute("Id",compid);
190 comp_elem.addAttribute("Guid",UUID.randomUUID().toString().toUpperCase());
191 comp_elem.addAttribute("DiskId",this.diskid);
192
193 Element file_elem = comp_elem.addElement("File");
194 file_elem.addAttribute("Id",('F' + idgen.next()));
195 file_elem.addAttribute("Name",namegen.next());
196 file_elem.addAttribute("LongName",f.getName());
197 file_elem.addAttribute("src",f.getAbsolutePath());
198 file_elem.addAttribute("KeyPath","yes");
199 file_elem.addAttribute("Vital","yes");
200
201
202 Element ref_elem = feature.addElement("ComponentRef");
203 ref_elem.addAttribute("Id",compid);
204
205
206 if (config) {
207
208 comp_elem.addAttribute("Permanent","yes");
209 comp_elem.addAttribute("NeverOverwrite","yes");
210
211 String compid_new = ('C' + idgen.next());
212
213 Element comp_elem_new = dir_elem.addElement("Component");
214 comp_elem_new.addAttribute("Id",compid_new);
215 comp_elem_new.addAttribute("Guid",UUID.randomUUID().toString().toUpperCase());
216 comp_elem_new.addAttribute("DiskId",this.diskid);
217
218 Element file_elem_new = comp_elem_new.addElement("File");
219 file_elem_new.addAttribute("Id",('F' + idgen.next()));
220 file_elem_new.addAttribute("Name",namegen.next());
221 file_elem_new.addAttribute("LongName",f.getName()+"-new");
222 file_elem_new.addAttribute("src",f.getAbsolutePath());
223 file_elem_new.addAttribute("KeyPath","yes");
224 file_elem_new.addAttribute("Vital","yes");
225
226 Element ref_elem_new = feature.addElement("ComponentRef");
227 ref_elem_new.addAttribute("Id",compid_new);
228 }
229
230 for (Shortcut s : this.desktopshortcuts) {
231
232 File shortcutfile = new File(this.srcdir,s.getFile());
233
234 if (f.equals(shortcutfile)) {
235
236 if (debug) handleOutput("Creating Desktop Shortcut ...");
237 addShortcut(file_elem,s,this.idprefix + "DesktopFolder");
238
239 }
240
241 }
242
243 for (Shortcut s : this.startmenueshortcuts) {
244
245 File shortcutfile = new File(this.srcdir,s.getFile());
246
247 if (f.equals(shortcutfile)) {
248
249 if (debug) handleOutput("Creating Startmenue Shortcut ...");
250
251 if (startmenuefolder != null)
252 addShortcut(file_elem,s,this.idprefix + "Start_Menue_Folder");
253 else
254 addShortcut(file_elem,s,this.idprefix + "ProgramMenuFolder");
255
256 }
257
258 }
259
260 }
261
262 if (f.isDirectory()) {
263
264 String id = idgen.next();
265 if (debug) handleOutput("Directory: "+f.getAbsolutePath()+" Id: "+id);
266
267 Element subdir_elem = dir_elem.addElement("Directory");
268 subdir_elem.addAttribute("Id",('D' + id));
269 subdir_elem.addAttribute("Name",namegen.next());
270 subdir_elem.addAttribute("LongName",f.getName());
271
272 proceedDirectory(subdir_elem,f);
273
274 }
275
276 }
277
278 }
279
280 /**
281 * Adds a Desktop / Startmenue shortcut for a file
282 *
283 * @param file The target file of the shortcut
284 * @param s Shortcut object
285 * @param shortcut_dir Reference to the diretory to place the shortcut
286 */
287 private void addShortcut(Element file, Shortcut s, String shortcut_dir) {
288
289 Element shortcut = file.addElement("Shortcut");
290 shortcut.addAttribute("Id",('S' + idgen.next()));
291 shortcut.addAttribute("Directory",shortcut_dir);
292 shortcut.addAttribute("LongName",s.getName());
293 shortcut.addAttribute("Name",namegen.next());
294
295 if (s.getWorkingdir() != null) shortcut.addAttribute("WorkingDirectory",s.getWorkingdir());
296
297 if (s.getArguments() != null) shortcut.addAttribute("Arguments",s.getArguments());
298
299 if (s.getIcon() != null) {
300
301 String iconid = ('I' + idgen.next());
302 shortcut.addAttribute("Icon",iconid);
303
304 File iconfile = new File(this.destdir,s.getIcon());
305 if (debug) handleOutput("Icon File: "+iconfile.getAbsolutePath());
306
307 Element icon = fragment.addElement("Icon");
308 icon.addAttribute("Id",iconid);
309 icon.addAttribute("src",iconfile.getAbsolutePath());
310
311 }
312
313 }
314
315
316
317
318 /**
319 * Fileset with configuration files
320 */
321 public Path createConfigfiles() {
322 if (this.configfiles == null) this.configfiles = new Path(getProject());
323 return this.configfiles.createPath();
324 }
325
326 /**
327 * Shortcut to place on the desktop
328 */
329 public void addDesktop(Shortcut s) {
330 this.desktopshortcuts.add(s);
331 }
332
333 /**
334 * Shortcut to place in the startmenue
335 */
336 public void addStartmenue(Shortcut s) {
337 this.startmenueshortcuts.add(s);
338 }
339
340 /**
341 * Enable debug output
342 */
343 public void setDebug(boolean debug) {
344 this.debug = debug;
345 }
346
347 /**
348 * The directory to create the file
349 */
350 public void setDestdir(File destdir) {
351 this.destdir = destdir;
352 }
353
354 /**
355 * The name of the fragment file
356 */
357 public void setFilename(String filename) {
358 this.filename = filename;
359 }
360
361 /**
362 * The id of the directory to reference
363 */
364 public void setDirectoryid(String directoryid) {
365 this.directoryid = directoryid;
366 }
367
368 /**
369 * The id of the feature to reference
370 */
371 public void setFeatureid(String featureid) {
372 this.featureid = featureid;
373 }
374
375 /**
376 * The id of the fragment
377 */
378 public void setFragmentid(String fragmentid) {
379 this.fragmentid = fragmentid;
380 }
381
382 /**
383 * Directory containing the the files to include
384 */
385 public void setSrcdir(File srcdir) {
386 this.srcdir = srcdir;
387 }
388
389 /**
390 * The diskid for the generated files
391 */
392 public void setDiskid(String diskid) {
393 this.diskid = diskid;
394 }
395
396
397 /**
398 * The folder inside the startmenue to place the shortcuts
399 */
400 public void setStartmenuefolder(String startmenuefolder) {
401 this.startmenuefolder = startmenuefolder;
402 }
403
404
405 /**
406 * Prefix for generated IDs
407 */
408 public void setIdprefix(String idprefix) {
409 this.idprefix = idprefix;
410 }
411
412
413 }