Source code: com/thermidor/build/tasks/InstallTask.java
1 package com.thermidor.build.tasks;
2 import org.apache.tools.ant.*;
3 import org.apache.tools.ant.taskdefs.*;
4 import org.apache.tools.ant.types.*;
5 import java.io.*;
6 import gnu.regexp.*;
7 import java.util.*;
8 /** goeff mitchell about an hour. Technical intrvew phone adrian after
9 * @author Edward Turnock
10 * @version 1.0
11 */
12 public class InstallTask extends Task{
13 /**
14 * Constant for the backup mode <i>none</i>.
15 */
16 public static final int NONE=0;
17 /**
18 * Constant for the backup mode <i>numbered</i>.
19 */
20 public static final int NUMBERED=1;
21 /**
22 * Constant for the backup mode <i>existing</i>.
23 */
24 public static final int EXISTING=2;
25 /**
26 * Constant for the backup mode <i>simple</i>.
27 */
28 public static final int SIMPLE=3;
29 /**
30 * String identitier of the backup mode <i>none</i>.
31 */
32 public static final String STR_NONE="none";
33 /**
34 * String identitier of the backup mode <i>numbered</i>.
35 */
36 public static final String STR_NUMBERED="numbered";
37 /**
38 * String identitier of the backup mode <i>existing</i>.
39 */
40 public static final String STR_EXISTING="existing";
41 /**
42 * String identitier of the backup mode <i>simple</i>.
43 */
44 public static final String STR_SIMPLE="simple";
45 /**
46 * The list of supported backup modes.
47 */
48 public static final String[] BACKUPS= {
49 STR_NONE,
50 STR_NUMBERED,
51 STR_EXISTING,
52 STR_SIMPLE
53 };
54 /**
55 * The ant enumerated attribute that will be used to constrain the available
56 * backup modes.
57 */
58 public static class BackupMode extends EnumeratedAttribute {
59 /**
60 * Return the available backup mode names.
61 * @return the backup modes.
62 */
63 public String[] getValues() {
64 return BACKUPS;
65 }
66 }
67 /**
68 * The sed based regular expression
69 * <code>^\(.*\.\)~\([[:digit:]]\+\)~$</code> that will be used to find
70 * numbered backups.
71 */
72 public static final String BACKUP_REGEXP=
73 "^\\(.*\\.\\)~\\([[:digit:]]\\+\\)~$";
74 /**
75 * The BackupFilenameFilter is used to retrieve all numbered backups of a
76 * particular filename.
77 * @author Edward Turnock
78 * @version 1.0
79 */
80 public static class BackupFilenameFilter implements FilenameFilter {
81 /**
82 * The regexp object that will be use in the filtering.
83 */
84 private RE _regexp;
85 /**
86 * The file name for which backups should be found.
87 */
88 private String _fileName;
89 /**
90 * Construct a new instance of a BackupFilenameFilter for the specified
91 * filename.
92 * @param fileName the name of the file for which backups should be found.
93 * @throws IOException is raised if the regexp could not be constructed.
94 */
95 public BackupFilenameFilter(String fileName) throws IOException {
96 _fileName=fileName;
97 try {
98 _regexp=new RE(BACKUP_REGEXP,0,RESyntax.RE_SYNTAX_SED);
99 }
100 catch(REException ree) {
101 throw new IOException("could not construct BackupFileNameFilter invalid regexp");
102 }
103 }
104 /**
105 * Should the specified file be included in the list.
106 * @param dir the directory that the filename filter is working in.
107 * @param name the name of the file to check.
108 * @return true if the specified file name was a backup of the name that
109 * this instance was constructed with, otherwise return false.
110 */
111 public boolean accept(File dir,String name) {
112 boolean retval=false;
113 REMatch match=_regexp.getMatch(name);
114 if(match!=null) {
115 String back=null;
116 int numStart=match.getStartIndex(1);
117 int numEnd=match.getEndIndex(1);
118 back=name.substring(numStart,numEnd);
119 retval=name.equals(back);
120 }
121 return retval;
122 }
123 /**
124 * This utility operation is provided to allow the backup number to be
125 * retrieved from the name of a file that has been basked up under the
126 * numbered backup scheme.
127 * @param name the name of a backup file.
128 * @return the numberof the backup.
129 */
130 public int backupNumber(String name) {
131 int retval=1;
132 REMatch match=_regexp.getMatch(name);
133 int numStart=match.getStartIndex(2);
134 int numEnd=match.getEndIndex(2);
135 retval=Integer.parseInt(name.substring(numStart,numEnd));
136 return retval;
137 }
138 }
139 /**
140 * The ManFilenameFilter is used to select all of the manpages in a
141 * particular directory. This is acchieved by accepting files based on the
142 * numbered section suffix.
143 */
144 public static class ManFilenameFilter implements FilenameFilter {
145 /**
146 * The manual section that we what to fileter file names for.
147 */
148 private String _section=null;
149 /**
150 * Construct a new ManFilenameFilter instance that will be used to retrieve
151 * man pages that belong to the specified manual section.
152 * @param section the section of the manual.
153 */
154 public ManFilenameFilter(String section) {
155 _section="."+section;
156 }
157 /**
158 * The name will be accepted if it does not correspond to a directory
159 * and its suffix is consistent with the manual section mane that the
160 * filter was constructed with.
161 * @param dir the directory that the filename filter is working in.
162 * @param name the name of the file to check.
163 * @return true if the specified file belongs to the manual section that
164 * this instance was contructed with, otherwise return false.
165 */
166 public boolean accept(File dir, String name) {
167 boolean retval=false;
168 File temp = new File(dir,name);
169 if(!temp.isDirectory()) {
170 retval = name.endsWith(_section);
171 }
172 return retval;
173 }
174 }
175 /**
176 * Directory name for manual section 1, <i>man1</i>
177 */
178 public static String STR_MAN_1="man1";
179 /**
180 * Directory name for manual section 2, <i>man2</i>
181 */
182 public static String STR_MAN_2="man2";
183 /**
184 * Directory name for manual section 3, <i>man3</i>
185 */
186 public static String STR_MAN_3="man3";
187 /**
188 * Directory name for manual section 4, <i>man4</i>
189 */
190 public static String STR_MAN_4="man4";
191 /**
192 * Directory name for manual section 5, <i>man5</i>
193 */
194 public static String STR_MAN_5="man5";
195 /**
196 * Directory name for manual section 6, <i>man6</i>
197 */
198 public static String STR_MAN_6="man6";
199 /**
200 * Directory name for manual section 7, <i>man7</i>
201 */
202 public static String STR_MAN_7="man7";
203 /**
204 * Directory name for manual section 8, <i>man8</i>
205 */
206 public static String STR_MAN_8="man8";
207 /**
208 * Directory name for manual section n, <i>mann</i>
209 */
210 public static String STR_MAN_n="mann";
211 /**
212 * The internal list of available manual directories.
213 */
214 private static final String[] MAN_DIRS={
215 STR_MAN_1,
216 STR_MAN_2,
217 STR_MAN_3,
218 STR_MAN_4,
219 STR_MAN_5,
220 STR_MAN_6,
221 STR_MAN_7,
222 STR_MAN_8,
223 STR_MAN_n
224 };
225 /**
226 * The MAN_TABLE hashtable is used to maintain the ManFilenameFilter for
227 * a given manula section aganst the name of the directory for that section.
228 */
229 private static Hashtable MAN_TABLE = new Hashtable();
230 /**
231 * Populate the MAN_TABLE with directory names and ManFilenameFilter's
232 */
233 static {
234 MAN_TABLE.put(STR_MAN_1,new ManFilenameFilter("1"));
235 MAN_TABLE.put(STR_MAN_2,new ManFilenameFilter("2"));
236 MAN_TABLE.put(STR_MAN_3,new ManFilenameFilter("3"));
237 MAN_TABLE.put(STR_MAN_4,new ManFilenameFilter("4"));
238 MAN_TABLE.put(STR_MAN_5,new ManFilenameFilter("5"));
239 MAN_TABLE.put(STR_MAN_6,new ManFilenameFilter("6"));
240 MAN_TABLE.put(STR_MAN_7,new ManFilenameFilter("7"));
241 MAN_TABLE.put(STR_MAN_8,new ManFilenameFilter("8"));
242 MAN_TABLE.put(STR_MAN_n,new ManFilenameFilter("n"));
243 }
244 /**
245 * The BACKUP_TABLE is used to maintain backup actions against there aliases.
246 * For example, STR_NUMBERED -> new BackupNumbered()
247 */
248 private static Hashtable BACKUP_TABLE = new Hashtable();
249 /**
250 * Populate the BACKUP_TABLE with backup alias action pairs.
251 */
252 static {
253 BACKUP_TABLE.put(STR_NONE,new BackupNone());
254 BACKUP_TABLE.put(STR_NUMBERED,new BackupNumbered());
255 BACKUP_TABLE.put(STR_EXISTING,new BackupExisting());
256 BACKUP_TABLE.put(STR_SIMPLE,new BackupSimple());
257 }
258 /**
259 * Retrieve the backup action for the specfied backup mode string.
260 * @param mode the backup mode that was selected.
261 * @return the backup action that corresponds to that mode.
262 * @throws BuildException is raised if the mode was not found.
263 */
264 protected static BackupAction getBackupAction(String mode) {
265 BackupAction retval = null;
266 retval=(BackupAction)BACKUP_TABLE.get(mode);
267 if(retval == null) {
268 throw new BuildException("unknown backup mode");
269 }
270 return retval;
271 }
272 /**
273 * The default backup suffix for simple backups. This is '~' the same suffix as used bu emacs and other GNU utilities.
274 */
275 public static String DEFAULT_SUFFIX="~";
276 /**
277 * Default and standard directory name for the bindir <i>bin</i>.
278 */
279 protected final static String BIN="bin";//_bindir//
280 /**
281 * Default and standard directory name for the docdir <i>doc</i>.
282 */
283 protected final static String DOC="doc";//_docdir//
284 /**
285 * Default and standard directory name for the sysconfdir <i>etc</i>.
286 */
287 protected final static String ETC="etc";//_sysconfdir//
288 /**
289 * Default and standard directory name for the libdir <i>lib</i>.
290 */
291 protected final static String LIB="lib";//_libdir//
292 /**
293 * Default and standard directory name for the sbindir <i>sbin</i>.
294 */
295 protected final static String SBIN="sbin";//_sbindir//
296 /**
297 * Default and standard directory name for the datadir <i>share</i>.
298 */
299 protected final static String SHARE="share";//_datadir//
300 /**
301 * Default and standard directory name for the localstatedir <i>var</i>.
302 */
303 protected final static String VAR="var";//_localstatedir//
304 /**
305 * Default and standard directory name for the root of the manual directory
306 * structure <i>man</i>.
307 */
308 protected final static String MAN="man";
309 /**
310 * The root of the direcotry structure from which the software should be
311 * installed.
312 */
313 private File _from=null;
314 /**
315 * The path prefix under which the software should be installed.
316 */
317 private File _prefix=null;
318 /**
319 * The <i>_bindir</i> directory will point the directory that executable
320 * components should be installed into. The default location for this is
321 * <code>${prefix}/bin</code>.
322 */
323 private File _bindir=null;
324 /**
325 * The <i>_sbindir</i> directory will point the directory that system
326 * executable components should be installed into. The default location
327 * for this is
328 * <code>${prefix}/sbin</code>.
329 */
330 private File _sbindir=null;
331 /**
332 * The <i>_libdir</i> directory will point the directory that library
333 * components should be installed into. The default location
334 * for this is
335 * <code>${prefix}/lib</code>.
336 */
337 private File _libdir=null;
338 /**
339 * The <i>_datadir</i> directory will point the directory that shared but
340 * static application data and file components should be installed into.
341 * The default location for this is
342 * <code>${prefix}/share</code>.
343 */
344 private File _datadir=null;
345 /**
346 * The <i>_sysconfdir</i> directory will point the directory where
347 * system configuration files and data should be should be installed into.
348 * The default location for this is
349 * <code>${prefix}/etc</code>.
350 */
351 private File _sysconfdir=null;
352 /**
353 * The <i>_localstatedir</i> directory will point the directory where
354 * application runtime data should be should be installed into.
355 * The default location for this is
356 * <code>${prefix}/var</code>.
357 */
358 private File _localstatedir=null;
359 /**
360 * The <i>_datadir</i> directory will point the directory that
361 * documentation components should be installed into.
362 * The default location for this is
363 * <code>${prefix}/doc</code>.
364 */
365 private File _docdir=null;
366 /**
367 * The <i>_mandir</i> directory will point the root directory that
368 * manual page components should be installed into.
369 * The default location for this is
370 * <code>${prefix}/man</code>.
371 */
372 private File _mandir=null;
373 /**
374 * The <b>Ant</b> target that should be executed before any of the software
375 * components are installed.
376 */
377 private String _preInstallTarget=null;
378 /**
379 * The <b>Ant</b> target that should be executed after the software
380 * components are installed.
381 */
382 private String _postInstallTarget=null;
383 /**
384 * The backup suffix that will actually be used the default value of this
385 * is defiend by <code>DEFAULT_SUFFIX</code>.
386 */
387 private String _suffix=DEFAULT_SUFFIX;
388 /**
389 * The backup mode that will be employed during the installation.
390 */
391 private BackupMode _backupMode=new BackupMode();
392 /**
393 * Set the default backup mode to <i>none</i>, <code>STR_NONE</code>.
394 */
395 {
396 _backupMode.setValue(STR_NONE);
397 }
398 /**
399 * The installation action for the <i>bindir</i>.
400 */
401 private Bin _bin=new Bin();
402 /**
403 * The installation action for the <i>docdir</i>.
404 */
405 private Doc _doc= new Doc();
406 /**
407 * The installation action for the <i>sysconfdir</i>.
408 */
409 private Etc _etc=new Etc();
410 /**
411 * The installation action for the <i>libdir</i>.
412 */
413 private Lib _lib=new Lib();
414 /**
415 * The installation action for the <i>datadir</i>.
416 */
417 private Share _share= new Share();
418 /**
419 * The installation action for the <i>sbindir</i>.
420 */
421 private Sbin _sbin=new Sbin();
422 /**
423 * The installation action for the <i>mandir</i> and its subdirectories.
424 */
425 private Man _man=new Man();
426 /**
427 * Copy the contents of a source file to a destintation file.
428 * @param src the ource file.
429 * @param dest the desitnation file.
430 * @throws IOException is raised if the file could not be copied.
431 */
432 private static void copyFileRaw(File src,File dest) throws IOException {
433 FileInputStream fis=new FileInputStream(src);
434 FileOutputStream fos = new FileOutputStream(dest);
435 copy(fis,fos);
436 fos.flush();
437 fos.getFD().sync();
438 fos.close();
439 }
440 /**
441 * Copy the contents of the specified input stream <b>in</b> to the
442 * specified output stream <b>out</b>
443 * @param in the input stream that contains the data
444 * @param out the output streamt hat the data should be written to.
445 * @throws IOException of the input stream could not be copied to the output
446 * stream.
447 */
448 private static void copy(InputStream in, OutputStream out) throws IOException {
449 byte[] buffer = new byte[1024];
450 int bytesRead = in.read(buffer);
451 while(bytesRead != -1 ) {
452 out.write(buffer, 0, bytesRead);
453 bytesRead = in.read(buffer);
454 }
455 }
456 /**
457 * The BackupAction class is an abstract action/command that should be
458 * executed to make a backup of a file.
459 * @author Edward Turnock
460 * @version 1.0
461 */
462 public static abstract class BackupAction {
463 /**
464 * Backup the specified file, using the supplied suffix if it is applicable
465 * to the backup mode that this instance implements.
466 * @param file the file to backup
467 * @param suffix the backup suffix that should be used.
468 * @throws IOException is raised if the file could not be backed up.
469 */
470 public abstract void backup(File file,String suffix) throws IOException ;
471 }
472 /**
473 * BackupNone is the simplest implementation of backup, in that it simply
474 * ignores the request to make a backup of the file.
475 * @author Edward Turnock
476 * @version 1.0
477 */
478 public static class BackupNone extends BackupAction {
479 /**
480 * Pretend to backup the specified file.
481 * @param file the file to backup
482 * @param suffix the backup suffix that should be used.
483 * @throws IOException is raised if the file could not be backed up.
484 */
485 public void backup(File file,String suffix) throws IOException {}
486 }
487 /**
488 * Make numbered backups of the files that are to be replaced. This mode
489 * follows the same for as that employed by the GNU file utils. For example
490 * the first backup will be of the form 'build.xml.~1~'
491 * @author Edward Turnock
492 * @version 1.0
493 */
494 public static class BackupNumbered extends BackupAction {
495 /**
496 * The <i>numbered</i> backup mode.
497 * Backup the specified file using the numbering scheme. In this case the
498 * suffix will be ignored. The numbering scheme ignores missing backup
499 * numbers and will always create a new backup that is on higher than
500 * any in the directory.
501 * @param file the file to backup.
502 * @param suffix the suffix to use. In this cse the suffix will be ignored.
503 * @throws IOException is raised if the file could not be backed up.
504 */
505 public void backup(File file,String suffix) throws IOException {
506 if(file.exists()) {
507 if(suffix == null) {
508 suffix = DEFAULT_SUFFIX;
509 }
510 File backupFile;
511 BackupFilenameFilter filter=new BackupFilenameFilter(file.getName());
512 String[] list=file.getParentFile().list(filter);
513 int len=list.length;
514 int highest=0;
515 for(int cnt = 0; cnt < len; cnt++) {
516 int temp=filter.backupNumber(list[cnt]);
517 if(temp>highest) {
518 highest=temp;
519 }
520 }
521 highest++;
522 backupFile=new File(file.getPath()+DEFAULT_SUFFIX+highest+DEFAULT_SUFFIX);
523 copyFileRaw(file,backupFile);
524 }
525 }
526 }
527 /**
528 * The <i>existing</i> backup mode. If the file to be installed already
529 * exists, but doesnot have a backup then do a simple backup of that file.
530 * If the file to be installed already has <i>numbered</i> backups
531 * determine what the next backup number would be and create a new backup
532 * with that number.
533 */
534 public static class BackupExisting extends BackupAction {
535 /**
536 * Make a backup of the specified file. The backup in this case will have
537 * the same file name but with the supplied suffix.
538 * @param file the file to backup.
539 * @param duffix the suffix that should be used.
540 */
541 public void backup(File file,String suffix) throws IOException {
542 if(file.exists()) {
543 if(suffix == null) {
544 suffix = DEFAULT_SUFFIX;
545 }
546 BackupFilenameFilter filter=new BackupFilenameFilter(file.getName());
547 String[] list=file.getParentFile().list(filter);
548 File backupFile = null;
549 if(list.length == 0) {
550 backupFile = new File(file.getPath()+suffix);
551 copyFileRaw(file,backupFile);
552 }
553 else {
554 int len=list.length;
555 int highest=0;
556 for(int cnt = 0; cnt < len; cnt++) {
557 int temp=filter.backupNumber(list[cnt]);
558 if(temp>highest) {
559 highest=temp;
560 }
561 }
562 highest++;
563 backupFile=new File(file.getPath()+DEFAULT_SUFFIX+highest+DEFAULT_SUFFIX);
564 copyFileRaw(file,backupFile);
565 }
566 }
567 }
568 }
569 /**
570 * The <i>simple</i> backup action. If the target file already exists, then
571 * make a single backup of it with the specified suffix. If the backup
572 * already exists then it is written over.
573 * @author Edward Turnock
574 * @version 1.0
575 */
576 public static class BackupSimple extends BackupAction {
577 /**
578 * Make a backup of the specified file. The backup in this case will have
579 * the same file name but with the supplied suffix.
580 * @param file the file to backup.
581 * @param duffix the suffix that should be used.
582 */
583 public void backup(File file,String suffix) throws IOException {
584 if(file.exists()) {
585 if(suffix == null) {
586 suffix = DEFAULT_SUFFIX;
587 }
588 File backupFile = new File(file.getPath()+suffix);
589 copyFileRaw(file,backupFile);
590 }
591 }
592 }
593 /**
594 * The <code>Dir</code> class is an abstract action to perform the
595 * installation of files to their appropriate target directories with the
596 * correct permissions, (if they apply on the underlying operating system).
597 * @author Edward Turnock
598 * @version 1.0
599 */
600 protected class Dir {
601 /**
602 * Copy a source file to a desintation file.
603 * @param src the source file.
604 * @param dest the destination file
605 * @param backupMode the backup mode that should be used to create backups
606 * of existing versions of the file.
607 * @param perm the permissions that the installed file should have.
608 */
609 protected void cp(File src,File dest,String backupMode,String suffix,String perm) {
610 if(!src.exists()) {
611 throw new BuildException("attempted to install non-existant file ["+src+"]");
612 }
613 File parent = dest.getParentFile();
614 if(parent != null && !parent.exists()) {
615 boolean result=parent.mkdirs();
616 if(!result) {
617 throw new BuildException("could not create destination directory ["+parent+"] check permisssions");
618 }
619 }
620 try {
621 getBackupAction(backupMode).backup(dest,suffix);
622 copyFileRaw(src,dest);
623 }
624 catch(IOException ioe) {
625 ioe.printStackTrace();
626 throw new BuildException("failed to copy file ["+src+"] with backup mode ["+backupMode+"]");
627 }
628 Chmod chmod = (Chmod)getProject().createTask("chmod");
629 chmod.setFile(dest);
630 chmod.setPerm(perm);
631 chmod.execute();
632 }
633 /**
634 * Find all the files in a tree that should be copied to a destination
635 * directory.
636 * @param files the list of files that is to be collected.
637 * @param traversedDirs the direcotries that have been traversed.
638 * @param fromDir the root dir for the copy.
639 * @throws IOException is raised if an error prevented the list from being
640 * constructed correctly.
641 */
642 protected void findFiles(Vector files,Vector traversedDirs,File fromDir) throws IOException {
643 String[] list=fromDir.list();
644 int len= list.length;
645 for (int cnt =0;cnt < len;cnt++) {
646 File temp=new File(fromDir,list[cnt]);
647 if(temp.isDirectory()) {
648 if(traversedDirs.contains(temp.getCanonicalFile())) {
649 continue;
650 }
651 traversedDirs.addElement(temp.getCanonicalFile());
652 findFiles(files,traversedDirs,temp);
653 }
654 else {
655 files.add(temp);
656 }
657 }
658 }
659 /**
660 * Copy one direcotry to another.
661 * @param fromDir the source directory,
662 * @param toDuir the destination directory.
663 * @param perm the permissions that the installed files should have.
664 */
665 protected void copyTree(File fromDir,File toDir,String perm) {
666 try {
667 String fromDirStr=fromDir.getCanonicalFile().getPath();
668 int fds=fromDirStr.length();
669 if(!fromDirStr.endsWith(File.separator)) {
670 fds++;
671 }
672 if(!fromDir.exists()) {
673 return;
674 }
675 Vector files=new Vector();
676 Vector traversed=new Vector();
677
678 findFiles(files,traversed,fromDir);
679
680 Enumeration e = files.elements();
681 while(e.hasMoreElements()) {
682 File tp=((File)e.nextElement()).getCanonicalFile();
683 String tpstr=tp.getPath();
684 File dest=new File(toDir,tpstr.substring(fds));
685 cp(tp,dest,_backupMode.getValue(),_suffix,perm);
686 }
687 }
688 catch(IOException ioe) {
689 throw new BuildException("failed to copy tree ["+fromDir+"] with backup mode ["+_backupMode.getValue()+"]");
690 }
691 }
692 }
693 /**
694 * The bin installation action. This action assumes that there sould
695 * be no subdirectories to <i>bindir</i> and will warn the user that it will
696 * not be installing those subdirectries.
697 * @author Edward Turnock
698 * @version 1.0
699 */
700 public class Bin extends Dir {
701 /**
702 * The permission that will be applied to all files installed in the
703 * <i>bindir</i>, the default is <code>u=rwx,go=rx</code>.
704 */
705 private String _perm="u=rwx,go=rx";
706 /**
707 * Set the permission set for all files installed by this action.
708 * @param perm the permission set.
709 */
710 public void setPerm(String perm) {
711 _perm=perm;
712 }
713 /**
714 * Execute the installation of all files in the build output bin directory
715 * to the specifed <i>bindir</i>.
716 */
717 public void execute() {
718 File toDir=null;
719 if(_bindir==null) {
720 toDir=new File(_prefix,BIN);
721 }
722 else {
723 toDir = _bindir;
724 }
725 File fromDir=new File(_from,BIN);
726 if(!fromDir.exists()) {
727 return;
728 }
729 String[] list=fromDir.list();
730 int len= list.length;
731 for (int cnt =0;cnt < len;cnt++) {
732 File temp=new File(fromDir,list[cnt]);
733 if(temp.isDirectory()) {
734 getProject().log("Install does not support sub directories of bin",Project.MSG_WARN);
735 continue;
736
737 }
738 File dest=new File(toDir,list[cnt]);
739 cp(temp,dest,_backupMode.getValue(),_suffix,_perm);
740 }
741 }
742 }
743 /**
744 * The <i>docdir</i> installation action.
745 * @author Edward Turnock
746 * @version 1.0
747 */
748 public class Doc extends Dir {
749 /**
750 * The permission that will be applied to all files installed in the
751 * <i>docdir</i>, the default is <code>u=rw,go=r</code>.
752 */
753 private String _perm="u=rw,go=r";
754 /**
755 * Set the permission set for all files installed by this action.
756 * @param perm the permission set.
757 */
758 public void setPerm(String perm) {
759 _perm=perm;
760 }
761 /**
762 * Install the contents of the <b>doc</b> direcotry of the builds output,
763 * including all subdirecotries to the specfied <i>docdir</i> applying
764 * the appropriate permissions.
765 */
766 public void execute() {
767 File toDir=null;
768 if(_docdir==null) {
769 toDir=new File(_prefix,DOC);
770 }
771 else {
772 toDir = _docdir;
773 }
774 File fromDir=new File(_from,DOC);
775 copyTree(fromDir,toDir,_perm);
776 }
777 }
778 /**
779 * The <i>sysconfdir</i> isntallation action.
780 * @author Edward Turnock
781 * @version 1.0
782 */
783 public class Etc extends Dir {
784 /**
785 * The permission that will be applied to all files installed in the
786 * <i>sysconfdir</i>, the default is <code>u=rw,go=r</code>.
787 */
788 private String _perm="u=rw,go=r";
789 /**
790 * Set the permission set for all files installed by this action.
791 * @param perm the permission set.
792 */
793 public void setPerm(String perm) {
794 _perm=perm;
795 }
796 /**
797 * Install the contents of the <b>etc</b> direcotry of the builds output,
798 * including all subdirecotries to the specfied <i>sysconfdir</i> applying
799 * the appropriate permissions.
800 */
801 public void execute() {
802 File toDir=null;
803 if(_sysconfdir==null) {
804 toDir=new File(_prefix,ETC);
805 }
806 else {
807 toDir = _sysconfdir;
808 }
809 File fromDir=new File(_from,ETC);
810 copyTree(fromDir,toDir,_perm);
811 }
812 }
813 /**
814 * The <i>libdir</i> installation action.
815 * @author Edward Turnock
816 * @version 1.0
817 */
818 public class Lib extends Dir {
819 /**
820 * The permission that will be applied to all files installed in the
821 * <i>libdir</i>, the default is <code>u=rwx,go=rx</code>.
822 */
823 private String _perm="u=rwx,go=rx";
824 /**
825 * Set the permission set for all files installed by this action.
826 * @param perm the permission set.
827 */
828 public void setPerm(String perm) {
829 _perm=perm;
830 }
831 /**
832 * Install the contents of the <b>lib</b> direcotry of the builds output,
833 * including all subdirecotries to the specfied <i>libdir</i> applying
834 * the appropriate permissions.
835 */
836 public void execute() {
837 File toDir=null;
838 if(_libdir==null) {
839 toDir=new File(_prefix,LIB);
840 }
841 else {
842 toDir = _libdir;
843 }
844 File fromDir=new File(_from,LIB);
845 copyTree(fromDir,toDir,_perm);
846 }
847 }
848 /**
849 * The system bin installation action. This action assumes that there sould
850 * be no subdirectories to <i>sbindir</i> and will warn the user that it will
851 * not be installing those subdirectries.
852 * @author Edward Turnock
853 * @version 1.0
854 */
855 public class Sbin extends Dir {
856 /**
857 * The permission that will be applied to all files installed in the
858 * sbindir, the default is <code>u=rwx,go=rx</code>.
859 */
860 private String _perm="u=rwx,go=rx";
861 /**
862 * Set the permission set for all files installed by this action.
863 * @param perm the permission set.
864 */
865 public void setPerm(String perm) {
866 _perm=perm;
867 }
868 /**
869 * Execute the installation of all files in the build output bin directory
870 * to the specifed <i>sbindir</i>.
871 */
872 public void execute() {
873 File toDir=null;
874 if(_sbindir==null) {
875 toDir=new File(_prefix,SBIN);
876 }
877 else {
878 toDir = _sbindir;
879 }
880 File fromDir=new File(_from,SBIN);
881 if(!fromDir.exists()) {
882 return;
883 }
884 String[] list=fromDir.list();
885 int len= list.length;
886 for (int cnt =0;cnt < len;cnt++) {
887 File temp=new File(fromDir,list[cnt]);
888 if(temp.isDirectory()) {
889 getProject().log("Install does not support sub directories of sbin",Project.MSG_WARN);
890 continue;
891
892 }
893 File dest=new File(toDir,list[cnt]);
894 cp(temp,dest,_backupMode.getValue(),_suffix,_perm);
895 }
896 }
897 }
898 /**
899 * The manual page installation action. This action currently assumes that
900 * all generated manpages will be output, prior to installation, into a
901 * single directory <code>${out}/man</code>. The action will determine which
902 * section of the manual that they should be installed in bases on the
903 * suffix of the file.
904 * @author Edward Turnock
905 * @version 1.0
906 */
907 protected class Man extends Dir {
908 /**
909 * The permissions that should be applied to all installed manual pages.
910 * By default this is <code>u=rw,go=r</code>.
911 */
912 private String _perm="u=rw,go=r";
913 /**
914 * Set the permission set for all files installed by this action.
915 * @param perm the permission set.
916 */
917 public void setPerm(String perm) {
918 _perm=perm;
919 }
920 /**
921 * Execute the installation of manual pages, backing up existing files
922 * based on the backup mode employed by the installation task.
923 */
924 public void execute() {
925 File toDir=null;
926 if(_mandir == null) {
927 toDir = new File(_prefix,MAN);
928 }
929 else {
930 toDir = _mandir;
931 }
932 File fromDir=new File(_from,MAN);
933 if(!fromDir.exists()) {
934 return;
935 }
936 for(int cnt = 0 ; cnt < MAN_DIRS.length ; cnt++) {
937 String currentManDir=MAN_DIRS[cnt];
938 String[] results = fromDir.list
939 ((FilenameFilter)MAN_TABLE.get(currentManDir));
940 int len = 0;
941 if(results == null) {
942 len = 0;
943 }
944 else {
945 len = results.length;
946 }
947 if(results.length == 0) {
948 break;
949 }
950 File destDir = new File(toDir,currentManDir);
951 if(!destDir.exists()) {
952 boolean created = destDir.mkdirs();
953 if(!created) {
954 throw new BuildException("could not create man destination [" +
955 currentManDir + "]");
956 }
957 }
958 for(int cnt1 = 0; cnt1 < len ; cnt1++) {
959 File temp = new File(fromDir,results[cnt1]);
960 File tempDest = new File(destDir,results[cnt1]);
961 cp(temp,tempDest,_backupMode.getValue(),_suffix,_perm);
962 }
963 }
964 }
965 }
966 /**
967 * Install the content of the build output directory <b>share</b> to the
968 * specified <i>datadir</i>
969 */
970 protected class Share extends Dir {
971 /**
972 * The permissions that should be applied to all files installed in the
973 * <i>datadir</i> by the installation process.
974 */
975 private String _perm="u=rw,go=r";
976 /**
977 * Set the permission set for all files installed by this action.
978 * @param perm the permission set.
979 */
980 public void setPerm(String perm) {
981 _perm=perm;
982 }
983 /**
984 * Install the contents of the <b>share</b> direcotry of the builds output,
985 * including all subdirecotries to the specfied <i>datadir</i> applying
986 * the appropriate permissions.
987 */
988 public void execute() {
989 File toDir=null;
990 if(_datadir==null) {
991 toDir=new File(_prefix,SHARE);
992 }
993 else {
994 toDir = _datadir;
995 }
996 File fromDir=new File(_from,SHARE);
997 copyTree(fromDir,toDir,_perm);
998 }
999 }
1000 /**
1001 * If the install task has been asked to make simple backups of files
1002 * that it will replace then the value of this parameter will be used.
1003 * @param backupSuffix the backup suffix
1004 */
1005 public void setBackupsuffix(String backupSuffix) {
1006 _suffix=backupSuffix;
1007 }
1008 /**
1009 * Set the backup mode that should be used.
1010 */
1011 public void setBackupmode(BackupMode backupMode) {
1012 _backupMode = backupMode;
1013 }
1014 /**
1015 * Set the documentation directory. This will override the default
1016 * <i>${prefix}/doc</i>.
1017 * @param docdir the documentation directory.
1018 */
1019 public void setDocdir(File docdir) {
1020 _docdir=docdir;
1021 }
1022 /**
1023 * Set ther root direcotry from which installation will take place.
1024 * @param from the root directory of the built software.
1025 */
1026 public void setFrom(File from) {
1027 _from = from;
1028 }
1029 public void setPrefix(File prefix) {
1030 _prefix=prefix;
1031 }
1032 /**
1033 * Set the bin directory. This will override the default
1034 * <i>${prefix}/bin</i>.
1035 * @param bindir the bin directory.
1036 */
1037 public void setBindir(File bindir) {
1038 _bindir=bindir;
1039 }
1040 /**
1041 * Set the library directory. This will override the default
1042 * <i>${prefix}/lib</i>.
1043 * @param libdir the bin directory.
1044 */
1045 public void setLibdir(File libdir) {
1046 _libdir=libdir;
1047 }
1048 /**
1049 * Set the system bin directory. This will override the default
1050 * <i>${prefix}/sbin</i>.
1051 * @param sbindir the bin directory.
1052 */
1053 public void setSbindir(File sbindir) {
1054 _sbindir=sbindir;
1055 }
1056 /**
1057 * Set the shared data directory. This will override the default
1058 * <i>${prefix}/share</i>.
1059 * @param datadir the bin directory.
1060 */
1061 public void setDatadir(File datadir) {
1062 _datadir=datadir;
1063 }
1064 /**
1065 * Set the system configuration directory. This will override the default
1066 * <i>${prefix}/etc</i>.
1067 * @param sysconfdir the bin directory.
1068 */
1069 public void setSysconfdir(File sysconfdir) {
1070 _sysconfdir=sysconfdir;
1071 }
1072 /**
1073 * Set the root manual page directory. This will override the default
1074 * <i>${prefix}/man</i>.
1075 * @param mandir the bin directory.
1076 */
1077 public void setMandir(File mandir) {
1078 _mandir=mandir;
1079 }
1080 /**
1081 * Set the application data directory. This will override the default
1082 * <i>${prefix}/var</i>.
1083 * @param localstatedir the bin directory.
1084 */
1085 public void setLocalstatedir(File localstatedir) {
1086 _localstatedir=localstatedir;
1087 }
1088 /**
1089 * Set the <b>Ant</b> target that should be executed before installation.
1090 * @param target the target that should be executed.
1091 */
1092 public void setPreinstalltarget(String target) {
1093 _preInstallTarget=target;
1094 }
1095 /**
1096 * Set the <b>Ant</b> target that should be executed after installation.
1097 * @param target the target that should be executed.
1098 */
1099 public void setPostinstalltarget(String target) {
1100 _postInstallTarget=target;
1101 }
1102 /**
1103 * Execute the installation. If <b>preinstallationtarget</b> has been set
1104 * then that target will be executed before each of the directories has
1105 * been installed. if <b>postinstallationtarget</b> has been set then it
1106 * will be executed after all of the installation steps have been executed.
1107 */
1108 public void execute() {
1109 if(_from == null) {
1110 throw new BuildException("'from' attribute must be set");
1111 }
1112 if(_prefix == null) {
1113 throw new BuildException("'prefix' attribute must be set");
1114 }
1115 //executePreinstall target
1116 if(_preInstallTarget!=null) {
1117 getProject().executeTarget(_preInstallTarget);
1118 }
1119 _bin.execute();
1120 _doc.execute();
1121 _etc.execute();
1122 _lib.execute();
1123 _share.execute();
1124 _sbin.execute();
1125 _man.execute();
1126 //executePostInstall target
1127 if(_postInstallTarget!=null) {
1128 getProject().executeTarget(_postInstallTarget);
1129 }
1130 }
1131 /**
1132 * Create the sub-tag and action for the <i>bindir</i>.
1133 * @return the Bin install action.
1134 */
1135 public Bin createBin() {
1136 return _bin;
1137 }
1138 /**
1139 * Create the sub-tag and action for the <i>docdir</i>.
1140 * @return the Doc install action.
1141 */
1142 public Doc createDoc() {
1143 return _doc;
1144 }
1145 /**
1146 * Create the sub-tag and action for the <i>sysconfdir</i>.
1147 * @return the Etc install action.
1148 */
1149 public Etc createEtc() {
1150 return _etc;
1151 }
1152 /**
1153 * Create the sub-tag and action for the <i>libdir</i>.
1154 * @return the Lib install action.
1155 */
1156 public Lib createLib() {
1157 return _lib;
1158 }
1159 /**
1160 * Create the sub-tag and action for the <i>datadir</i>.
1161 * @return the Share install action.
1162 */
1163 public Share createShare() {
1164 return _share;
1165 }
1166 /**
1167 * Create the sub-tag and action for the <i>sbindir</i>.
1168 * @return the Sbin install action.
1169 */
1170 public Sbin createSbin() {
1171 return _sbin;
1172 }
1173 /**
1174 * Create the sub-tag and action for the <i>mandir</i>.
1175 * @return the man install action.
1176 */
1177 public Man createMan() {
1178 return _man;
1179 }
1180}
1181
1182