PageRenderTime 50ms CodeModel.GetById 34ms app.highlight 13ms RepoModel.GetById 1ms app.codeStats 1ms

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