PageRenderTime 45ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/jEdit/tags/jedit-4-3-pre5/de/masters_of_disaster/ant/tasks/ar/ArEntry.java

#
Java | 355 lines | 123 code | 38 blank | 194 comment | 7 complexity | b6c658e87c9ccc4fcfdb78c260c49556 MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-1.0, Apache-2.0, LGPL-2.0, LGPL-3.0, GPL-2.0, CC-BY-SA-3.0, LGPL-2.1, GPL-3.0, MPL-2.0-no-copyleft-exception, IPL-1.0
  1. package de.masters_of_disaster.ant.tasks.ar;
  2. import java.io.File;
  3. import java.util.Date;
  4. /**
  5. * This class represents an entry in an Ar archive. It consists
  6. * of the entry's header, as well as the entry's File. Entries
  7. * can be instantiated in one of three ways, depending on how
  8. * they are to be used.
  9. * <p>
  10. * ArEntries that are created from the header bytes read from
  11. * an archive are instantiated with the ArEntry( byte[] )
  12. * constructor. These entries will be used when extracting from
  13. * or listing the contents of an archive. These entries have their
  14. * header filled in using the header bytes. They also set the File
  15. * to null, since they reference an archive entry not a file.
  16. * <p>
  17. * ArEntries that are created from Files that are to be written
  18. * into an archive are instantiated with the ArEntry( File )
  19. * constructor. These entries have their header filled in using
  20. * the File's information. They also keep a reference to the File
  21. * for convenience when writing entries.
  22. * <p>
  23. * Finally, ArEntries can be constructed from nothing but a name.
  24. * This allows the programmer to construct the entry by hand, for
  25. * instance when only an InputStream is available for writing to
  26. * the archive, and the header information is constructed from
  27. * other information. In this case the header fields are set to
  28. * defaults and the File is set to null.
  29. *
  30. * <p>
  31. * The C structure for an Ar Entry's header is:
  32. * <pre>
  33. * struct header {
  34. * char filename[16];
  35. * char filedate[12];
  36. * char uid[6];
  37. * char gid[6];
  38. * char mode[8];
  39. * char size[10];
  40. * char magic[2];
  41. * } header;
  42. * </pre>
  43. *
  44. */
  45. public class ArEntry implements ArConstants {
  46. /** The entry's filename. */
  47. private StringBuffer filename;
  48. /** The entry's file date. */
  49. private long fileDate;
  50. /** The entry's user id. */
  51. private int userId;
  52. /** The entry's group id. */
  53. private int groupId;
  54. /** The entry's permission mode. */
  55. private int mode;
  56. /** The entry's size. */
  57. private long size;
  58. /** The entry's magic tag. */
  59. private StringBuffer magic;
  60. /** The entry's file reference */
  61. private File file;
  62. /** Default permissions bits for files */
  63. public static final int DEFAULT_FILE_MODE = 0100644;
  64. /** Convert millis to seconds */
  65. public static final int MILLIS_PER_SECOND = 1000;
  66. /**
  67. * Construct an empty entry and prepares the header values.
  68. */
  69. private ArEntry () {
  70. this.magic = new StringBuffer(HEADERMAGIC);
  71. this.filename = new StringBuffer();
  72. this.userId = 0;
  73. this.groupId = 0;
  74. this.file = null;
  75. }
  76. /**
  77. * Construct an entry with only a name. This allows the programmer
  78. * to construct the entry's header "by hand". File is set to null.
  79. *
  80. * @param name the entry name
  81. */
  82. public ArEntry(String name) {
  83. this();
  84. if (name.endsWith("/")) {
  85. throw new IllegalArgumentException("ar archives can only contain files");
  86. }
  87. this.filename = new StringBuffer(name);
  88. this.mode = DEFAULT_FILE_MODE;
  89. this.userId = 0;
  90. this.groupId = 0;
  91. this.size = 0;
  92. this.fileDate = (new Date()).getTime() / MILLIS_PER_SECOND;
  93. }
  94. /**
  95. * Construct an entry for a file. File is set to file, and the
  96. * header is constructed from information from the file.
  97. *
  98. * @param file The file that the entry represents.
  99. */
  100. public ArEntry(File file) {
  101. this();
  102. if (file.isDirectory()) {
  103. throw new IllegalArgumentException("ar archives can only contain files");
  104. }
  105. this.file = file;
  106. this.filename = new StringBuffer(file.getName());
  107. this.fileDate = file.lastModified() / MILLIS_PER_SECOND;
  108. this.mode = DEFAULT_FILE_MODE;
  109. this.size = file.length();
  110. }
  111. /**
  112. * Construct an entry from an archive's header bytes. File is set
  113. * to null.
  114. *
  115. * @param headerBuf The header bytes from an ar archive entry.
  116. */
  117. public ArEntry(byte[] headerBuf) {
  118. this();
  119. this.parseArHeader(headerBuf);
  120. }
  121. /**
  122. * Determine if the two entries are equal. Equality is determined
  123. * by the header names being equal.
  124. *
  125. * @param it Entry to be checked for equality.
  126. * @return True if the entries are equal.
  127. */
  128. public boolean equals(ArEntry it) {
  129. return this.getFilename().equals(it.getFilename());
  130. }
  131. /**
  132. * Determine if the two entries are equal. Equality is determined
  133. * by the header names being equal.
  134. *
  135. * @param it Entry to be checked for equality.
  136. * @return True if the entries are equal.
  137. */
  138. public boolean equals(Object it) {
  139. if (it == null || getClass() != it.getClass()) {
  140. return false;
  141. }
  142. return equals((ArEntry) it);
  143. }
  144. /**
  145. * Hashcodes are based on entry names.
  146. *
  147. * @return the entry hashcode
  148. */
  149. public int hashCode() {
  150. return getFilename().hashCode();
  151. }
  152. /**
  153. * Get this entry's name.
  154. *
  155. * @return This entry's name.
  156. */
  157. public String getFilename() {
  158. return this.filename.toString();
  159. }
  160. /**
  161. * Set this entry's name.
  162. *
  163. * @param name This entry's new name.
  164. */
  165. public void setFilename(String filename) {
  166. this.filename = new StringBuffer(filename);
  167. }
  168. /**
  169. * Set the mode for this entry
  170. *
  171. * @param mode the mode for this entry
  172. */
  173. public void setMode(int mode) {
  174. this.mode = mode;
  175. }
  176. /**
  177. * Get this entry's user id.
  178. *
  179. * @return This entry's user id.
  180. */
  181. public int getUserId() {
  182. return this.userId;
  183. }
  184. /**
  185. * Set this entry's user id.
  186. *
  187. * @param userId This entry's new user id.
  188. */
  189. public void setUserId(int userId) {
  190. this.userId = userId;
  191. }
  192. /**
  193. * Get this entry's group id.
  194. *
  195. * @return This entry's group id.
  196. */
  197. public int getGroupId() {
  198. return this.groupId;
  199. }
  200. /**
  201. * Set this entry's group id.
  202. *
  203. * @param groupId This entry's new group id.
  204. */
  205. public void setGroupId(int groupId) {
  206. this.groupId = groupId;
  207. }
  208. /**
  209. * Convenience method to set this entry's group and user ids.
  210. *
  211. * @param userId This entry's new user id.
  212. * @param groupId This entry's new group id.
  213. */
  214. public void setIds(int userId, int groupId) {
  215. this.setUserId(userId);
  216. this.setGroupId(groupId);
  217. }
  218. /**
  219. * Set this entry's modification time. The parameter passed
  220. * to this method is in "Java time".
  221. *
  222. * @param time This entry's new modification time.
  223. */
  224. public void setFileDate(long time) {
  225. this.fileDate = time / MILLIS_PER_SECOND;
  226. }
  227. /**
  228. * Set this entry's modification time.
  229. *
  230. * @param time This entry's new modification time.
  231. */
  232. public void setFileDate(Date time) {
  233. this.fileDate = time.getTime() / MILLIS_PER_SECOND;
  234. }
  235. /**
  236. * Get this entry's modification time.
  237. *
  238. * @return time This entry's new modification time.
  239. */
  240. public Date getFileDate() {
  241. return new Date(this.fileDate * MILLIS_PER_SECOND);
  242. }
  243. /**
  244. * Get this entry's file.
  245. *
  246. * @return This entry's file.
  247. */
  248. public File getFile() {
  249. return this.file;
  250. }
  251. /**
  252. * Get this entry's mode.
  253. *
  254. * @return This entry's mode.
  255. */
  256. public int getMode() {
  257. return this.mode;
  258. }
  259. /**
  260. * Get this entry's file size.
  261. *
  262. * @return This entry's file size.
  263. */
  264. public long getSize() {
  265. return this.size;
  266. }
  267. /**
  268. * Set this entry's file size.
  269. *
  270. * @param size This entry's new file size.
  271. */
  272. public void setSize(long size) {
  273. this.size = size;
  274. }
  275. /**
  276. * Write an entry's header information to a header buffer.
  277. *
  278. * @param outbuf The tar entry header buffer to fill in.
  279. */
  280. public void writeEntryHeader(byte[] outbuf) {
  281. int offset = 0;
  282. offset = ArUtils.getNameBytes(this.filename, outbuf, offset, NAMELEN);
  283. offset = ArUtils.getLongBytes(this.fileDate, outbuf, offset, FILEDATELEN);
  284. offset = ArUtils.getIntegerBytes(this.userId, outbuf, offset, UIDLEN);
  285. offset = ArUtils.getIntegerBytes(this.groupId, outbuf, offset, GIDLEN);
  286. offset = ArUtils.getOctalBytes(this.mode, outbuf, offset, MODELEN);
  287. offset = ArUtils.getLongBytes(this.size, outbuf, offset, SIZELEN);
  288. offset = ArUtils.getNameBytes(this.magic, outbuf, offset, MAGICLEN);
  289. while (offset < outbuf.length) {
  290. outbuf[offset++] = 0;
  291. }
  292. }
  293. /**
  294. * Parse an entry's header information from a header buffer.
  295. *
  296. * @param header The ar entry header buffer to get information from.
  297. */
  298. public void parseArHeader(byte[] header) {
  299. throw new UnsupportedOperationException("parseArHeader(byte[]) not yet implmented");
  300. // int offset = 0;
  301. //
  302. // this.filename = TarUtils.parseName(header, offset, NAMELEN);
  303. // offset += NAMELEN;
  304. // this.fileDate = TarUtils.parseOctal(header, offset, FILEDATELEN);
  305. // offset += FILEDATELEN;
  306. // this.userId = (int) TarUtils.parseOctal(header, offset, UIDLEN);
  307. // offset += UIDLEN;
  308. // this.groupId = (int) TarUtils.parseOctal(header, offset, GIDLEN);
  309. // offset += GIDLEN;
  310. // this.mode = (int) TarUtils.parseOctal(header, offset, MODELEN);
  311. // offset += MODELEN;
  312. // this.size = TarUtils.parseOctal(header, offset, SIZELEN);
  313. // offset += SIZELEN;
  314. // this.magic = TarUtils.parseName(header, offset, MAGICLEN);
  315. // offset += MAGICLEN;
  316. }
  317. }