1 package de.masters_of_disaster.ant.tasks.ar; 2 3 import java.io.BufferedOutputStream ; 4 import java.io.File ; 5 import java.io.FileInputStream ; 6 import java.io.FileOutputStream ; 7 import java.io.IOException ; 8 import java.util.Enumeration ; 9 import java.util.Vector ; 10 import org.apache.tools.ant.BuildException; 11 import org.apache.tools.ant.DirectoryScanner; 12 import org.apache.tools.ant.Project; 13 import org.apache.tools.ant.taskdefs.MatchingTask; 14 import org.apache.tools.ant.types.EnumeratedAttribute; 15 import org.apache.tools.ant.types.FileSet; 16 import org.apache.tools.ant.util.FileUtils; 17 import org.apache.tools.ant.util.MergingMapper; 18 import org.apache.tools.ant.util.SourceFileScanner; 19 import org.apache.tools.zip.UnixStat; 20 21 26 public class Ar extends MatchingTask { 27 File destFile; 28 File baseDir; 29 30 private ArLongFileMode longFileMode = new ArLongFileMode(); 31 32 Vector filesets = new Vector (); 33 34 37 private boolean longWarningGiven = false; 38 39 43 public ArFileSet createArFileSet() { 44 ArFileSet fileset = new ArFileSet(); 45 filesets.addElement(fileset); 46 return fileset; 47 } 48 49 50 54 public void setDestFile(File destFile) { 55 this.destFile = destFile; 56 } 57 58 62 public void setBasedir(File baseDir) { 63 this.baseDir = baseDir; 64 } 65 66 81 public void setLongfile(ArLongFileMode mode) { 82 this.longFileMode = mode; 83 } 84 85 89 public void execute() throws BuildException { 90 if (destFile == null) { 91 throw new BuildException("destFile attribute must be set!", 92 getLocation()); 93 } 94 95 if (destFile.exists() && destFile.isDirectory()) { 96 throw new BuildException("destFile is a directory!", 97 getLocation()); 98 } 99 100 if (destFile.exists() && !destFile.canWrite()) { 101 throw new BuildException("Can not write to the specified destFile!", 102 getLocation()); 103 } 104 105 Vector savedFileSets = (Vector ) filesets.clone(); 106 try { 107 if (baseDir != null) { 108 if (!baseDir.exists()) { 109 throw new BuildException("basedir does not exist!", 110 getLocation()); 111 } 112 113 ArFileSet mainFileSet = new ArFileSet(fileset); 115 mainFileSet.setDir(baseDir); 116 filesets.addElement(mainFileSet); 117 } 118 119 if (filesets.size() == 0) { 120 throw new BuildException("You must supply either a basedir " 121 + "attribute or some nested filesets.", 122 getLocation()); 123 } 124 125 boolean upToDate = true; 128 for (Enumeration e = filesets.elements(); e.hasMoreElements();) { 129 ArFileSet fs = (ArFileSet) e.nextElement(); 130 String [] files = fs.getFiles(getProject()); 131 132 if (!archiveIsUpToDate(files, fs.getDir(getProject()))) { 133 upToDate = false; 134 } 135 136 for (int i = 0; i < files.length; ++i) { 137 if (destFile.equals(new File (fs.getDir(getProject()), 138 files[i]))) { 139 throw new BuildException("An ar file cannot include " 140 + "itself", getLocation()); 141 } 142 } 143 } 144 145 if (upToDate) { 146 log("Nothing to do: " + destFile.getAbsolutePath() 147 + " is up to date.", Project.MSG_INFO); 148 return; 149 } 150 151 log("Building ar: " + destFile.getAbsolutePath(), Project.MSG_INFO); 152 153 ArOutputStream aOut = null; 154 try { 155 aOut = new ArOutputStream( 156 new BufferedOutputStream ( 157 new FileOutputStream (destFile))); 158 if (longFileMode.isTruncateMode() 159 || longFileMode.isWarnMode()) { 160 aOut.setLongFileMode(ArOutputStream.LONGFILE_TRUNCATE); 161 } else if (longFileMode.isFailMode() 162 || longFileMode.isOmitMode()) { 163 aOut.setLongFileMode(ArOutputStream.LONGFILE_ERROR); 164 } else if (longFileMode.isBsdMode()) { 165 aOut.setLongFileMode(ArOutputStream.LONGFILE_BSD); 166 } else { 167 aOut.setLongFileMode(ArOutputStream.LONGFILE_GNU); 169 } 170 171 longWarningGiven = false; 172 for (Enumeration e = filesets.elements(); 173 e.hasMoreElements();) { 174 ArFileSet fs = (ArFileSet) e.nextElement(); 175 String [] files = fs.getFiles(getProject()); 176 if (files.length > 1 && fs.getFullpath().length() > 0) { 177 throw new BuildException("fullpath attribute may only " 178 + "be specified for " 179 + "filesets that specify a " 180 + "single file."); 181 } 182 for (int i = 0; i < files.length; i++) { 183 File f = new File (fs.getDir(getProject()), files[i]); 184 arFile(f, aOut, fs); 185 } 186 } 187 } catch (IOException ioe) { 188 String msg = "Problem creating AR: " + ioe.getMessage(); 189 throw new BuildException(msg, ioe, getLocation()); 190 } finally { 191 FileUtils.close(aOut); 192 } 193 } finally { 194 filesets = savedFileSets; 195 } 196 } 197 198 205 protected void arFile(File file, ArOutputStream aOut, ArFileSet arFileSet) 206 throws IOException { 207 FileInputStream fIn = null; 208 209 if (file.isDirectory()) { 210 return; 211 } 212 213 String fileName = file.getName(); 214 215 String fullpath = arFileSet.getFullpath(); 216 if (fullpath.length() > 0) { 217 fileName = fullpath.substring(fullpath.lastIndexOf('/')); 218 } 219 220 if (fileName.length() <= 0) { 222 return; 223 } 224 225 try { 226 if ((fileName.length() >= ArConstants.NAMELEN) 227 || (-1 != fileName.indexOf(' '))) { 228 if (longFileMode.isOmitMode()) { 229 log("Omitting: " + fileName, Project.MSG_INFO); 230 return; 231 } else if (longFileMode.isWarnMode()) { 232 if (!longWarningGiven) { 233 log("Resulting ar file contains truncated or space converted filenames", 234 Project.MSG_WARN); 235 longWarningGiven = true; 236 } 237 log("Entry: \"" + fileName + "\" longer than " 238 + ArConstants.NAMELEN + " characters or containing spaces.", 239 Project.MSG_WARN); 240 } else if (longFileMode.isFailMode()) { 241 throw new BuildException("Entry: \"" + fileName 242 + "\" longer than " + ArConstants.NAMELEN 243 + "characters or containting spaces.", getLocation()); 244 } 245 } 246 247 ArEntry ae = new ArEntry(fileName); 248 ae.setFileDate(file.lastModified()); 249 ae.setUserId(arFileSet.getUid()); 250 ae.setGroupId(arFileSet.getGid()); 251 ae.setMode(arFileSet.getMode()); 252 ae.setSize(file.length()); 253 254 aOut.putNextEntry(ae); 255 256 fIn = new FileInputStream (file); 257 258 byte[] buffer = new byte[8 * 1024]; 259 int count = 0; 260 do { 261 aOut.write(buffer, 0, count); 262 count = fIn.read(buffer, 0, buffer.length); 263 } while (count != -1); 264 265 aOut.closeEntry(); 266 } finally { 267 if (fIn != null) { 268 fIn.close(); 269 } 270 } 271 } 272 273 279 protected boolean archiveIsUpToDate(String [] files, File dir) { 280 SourceFileScanner sfs = new SourceFileScanner(this); 281 MergingMapper mm = new MergingMapper(); 282 mm.setTo(destFile.getAbsolutePath()); 283 return sfs.restrict(files, dir, null, mm).length == 0; 284 } 285 286 290 public static class ArFileSet extends FileSet { 291 private String [] files = null; 292 293 private int fileMode = UnixStat.FILE_FLAG | UnixStat.DEFAULT_FILE_PERM; 294 private int uid; 295 private int gid; 296 private String fullpath = ""; 297 298 304 public ArFileSet(FileSet fileset) { 305 super(fileset); 306 } 307 308 312 public ArFileSet() { 313 super(); 314 } 315 316 322 public String [] getFiles(Project p) { 323 if (files == null) { 324 DirectoryScanner ds = getDirectoryScanner(p); 325 files = ds.getIncludedFiles(); 326 } 327 328 return files; 329 } 330 331 337 public void setMode(String octalString) { 338 this.fileMode = 339 UnixStat.FILE_FLAG | Integer.parseInt(octalString, 8); 340 } 341 342 345 public int getMode() { 346 return fileMode; 347 } 348 349 353 public void setUid(int uid) { 354 this.uid = uid; 355 } 356 357 360 public int getUid() { 361 return uid; 362 } 363 364 368 public void setGid(int gid) { 369 this.gid = gid; 370 } 371 372 375 public int getGid() { 376 return gid; 377 } 378 379 386 public void setFullpath(String fullpath) { 387 this.fullpath = fullpath; 388 } 389 390 393 public String getFullpath() { 394 return fullpath; 395 } 396 } 397 398 401 public static class ArLongFileMode extends EnumeratedAttribute { 402 403 public static final String 404 WARN = "warn", 405 FAIL = "fail", 406 TRUNCATE = "truncate", 407 GNU = "gnu", 408 BSD = "bsd", 409 OMIT = "omit"; 410 411 private final String [] validModes = {WARN, FAIL, TRUNCATE, GNU, BSD, OMIT}; 412 413 414 public ArLongFileMode() { 415 super(); 416 setValue(WARN); 417 } 418 419 422 public String [] getValues() { 423 return validModes; 424 } 425 426 429 public boolean isTruncateMode() { 430 return TRUNCATE.equalsIgnoreCase(getValue()); 431 } 432 433 436 public boolean isWarnMode() { 437 return WARN.equalsIgnoreCase(getValue()); 438 } 439 440 443 public boolean isGnuMode() { 444 return GNU.equalsIgnoreCase(getValue()); 445 } 446 447 450 public boolean isBsdMode() { 451 return BSD.equalsIgnoreCase(getValue()); 452 } 453 454 457 public boolean isFailMode() { 458 return FAIL.equalsIgnoreCase(getValue()); 459 } 460 461 464 public boolean isOmitMode() { 465 return OMIT.equalsIgnoreCase(getValue()); 466 } 467 } 468 } 469 | Popular Tags |