1. /*
  2. * @(#)ZipEntry.java 1.31 00/02/02
  3. *
  4. * Copyright 1995-2000 Sun Microsystems, Inc. All Rights Reserved.
  5. *
  6. * This software is the proprietary information of Sun Microsystems, Inc.
  7. * Use is subject to license terms.
  8. *
  9. */
  10. package java.util.zip;
  11. import java.util.Date;
  12. /**
  13. * This class is used to represent a ZIP file entry.
  14. *
  15. * @version 1.31, 02/02/00
  16. * @author David Connelly
  17. */
  18. public
  19. class ZipEntry implements ZipConstants, Cloneable {
  20. String name; // entry name
  21. long time = -1; // modification time (in DOS time)
  22. long crc = -1; // crc-32 of entry data
  23. long size = -1; // uncompressed size of entry data
  24. long csize = -1; // compressed size of entry data
  25. int method = -1; // compression method
  26. byte[] extra; // optional extra field data for entry
  27. String comment; // optional comment string for entry
  28. // The following flags are used only by Zip{Input,Output}Stream
  29. int flag; // bit flags
  30. int version; // version needed to extract
  31. long offset; // offset of loc header
  32. /**
  33. * Compression method for uncompressed entries.
  34. */
  35. public static final int STORED = 0;
  36. /**
  37. * Compression method for compressed (deflated) entries.
  38. */
  39. public static final int DEFLATED = 8;
  40. static {
  41. /* load the zip library */
  42. java.security.AccessController.doPrivileged(
  43. new sun.security.action.LoadLibraryAction("zip"));
  44. initIDs();
  45. }
  46. private static native void initIDs();
  47. /**
  48. * Creates a new zip entry with the specified name.
  49. *
  50. * @param name the entry name
  51. * @exception NullPointerException if the entry name is null
  52. * @exception IllegalArgumentException if the entry name is longer than
  53. * 0xFFFF bytes
  54. */
  55. public ZipEntry(String name) {
  56. if (name == null) {
  57. throw new NullPointerException();
  58. }
  59. if (name.length() > 0xFFFF) {
  60. throw new IllegalArgumentException("entry name too long");
  61. }
  62. this.name = name;
  63. }
  64. /**
  65. * Creates a new zip entry with fields taken from the specified
  66. * zip entry.
  67. * @param e a zip Entry object
  68. */
  69. public ZipEntry(ZipEntry e) {
  70. name = e.name;
  71. time = e.time;
  72. crc = e.crc;
  73. size = e.size;
  74. csize = e.csize;
  75. method = e.method;
  76. extra = e.extra;
  77. comment = e.comment;
  78. }
  79. /*
  80. * Creates a new zip entry for the given name with fields initialized
  81. * from the specified jzentry data.
  82. */
  83. ZipEntry(String name, long jzentry) {
  84. this.name = name;
  85. initFields(jzentry);
  86. }
  87. private native void initFields(long jzentry);
  88. /*
  89. * Creates a new zip entry with fields initialized from the specified
  90. * jzentry data.
  91. */
  92. ZipEntry(long jzentry) {
  93. initFields(jzentry);
  94. }
  95. /**
  96. * Returns the name of the entry.
  97. * @return the name of the entry
  98. */
  99. public String getName() {
  100. return name;
  101. }
  102. /**
  103. * Sets the modification time of the entry.
  104. * @param time the entry modification time in number of milliseconds
  105. * since the epoch
  106. * @see #getTime()
  107. */
  108. public void setTime(long time) {
  109. this.time = javaToDosTime(time);
  110. }
  111. /**
  112. * Returns the modification time of the entry, or -1 if not specified.
  113. * @return the modification time of the entry, or -1 if not specified
  114. * @see #setTime(long)
  115. */
  116. public long getTime() {
  117. return time != -1 ? dosToJavaTime(time) : -1;
  118. }
  119. /**
  120. * Sets the uncompressed size of the entry data.
  121. * @param size the uncompressed size in bytes
  122. * @exception IllegalArgumentException if the specified size is less
  123. * than 0 or greater than 0xFFFFFFFF bytes
  124. * @see #getSize()
  125. */
  126. public void setSize(long size) {
  127. if (size < 0 || size > 0xFFFFFFFFL) {
  128. throw new IllegalArgumentException("invalid entry size");
  129. }
  130. this.size = size;
  131. }
  132. /**
  133. * Returns the uncompressed size of the entry data, or -1 if not known.
  134. * @return the uncompressed size of the entry data, or -1 if not known
  135. * @see #setSize(long)
  136. */
  137. public long getSize() {
  138. return size;
  139. }
  140. /**
  141. * Returns the size of the compressed entry data, or -1 if not known.
  142. * In the case of a stored entry, the compressed size will be the same
  143. * as the uncompressed size of the entry.
  144. * @return the size of the compressed entry data, or -1 if not known
  145. * @see #setCompressedSize(long)
  146. */
  147. public long getCompressedSize() {
  148. return csize;
  149. }
  150. /**
  151. * Sets the size of the compressed entry data.
  152. * @param csize the compressed size to set to
  153. * @see #getCompressedSize()
  154. */
  155. public void setCompressedSize(long csize) {
  156. this.csize = csize;
  157. }
  158. /**
  159. * Sets the CRC-32 checksum of the uncompressed entry data.
  160. * @param crc the CRC-32 value
  161. * @exception IllegalArgumentException if the specified CRC-32 value is
  162. * less than 0 or greater than 0xFFFFFFFF
  163. * @see #setCrc(long)
  164. */
  165. public void setCrc(long crc) {
  166. if (crc < 0 || crc > 0xFFFFFFFFL) {
  167. throw new IllegalArgumentException("invalid entry crc-32");
  168. }
  169. this.crc = crc;
  170. }
  171. /**
  172. * Returns the CRC-32 checksum of the uncompressed entry data, or -1 if
  173. * not known.
  174. * @return the CRC-32 checksum of the uncompressed entry data, or -1 if
  175. * not known
  176. * @see #getCrc()
  177. */
  178. public long getCrc() {
  179. return crc;
  180. }
  181. /**
  182. * Sets the compression method for the entry.
  183. * @param method the compression method, either STORED or DEFLATED
  184. * @exception IllegalArgumentException if the specified compression
  185. * method is invalid
  186. * @see #getMethod()
  187. */
  188. public void setMethod(int method) {
  189. if (method != STORED && method != DEFLATED) {
  190. throw new IllegalArgumentException("invalid compression method");
  191. }
  192. this.method = method;
  193. }
  194. /**
  195. * Returns the compression method of the entry, or -1 if not specified.
  196. * @return the compression method of the entry, or -1 if not specified
  197. * @see #setMethod(int)
  198. */
  199. public int getMethod() {
  200. return method;
  201. }
  202. /**
  203. * Sets the optional extra field data for the entry.
  204. * @param extra the extra field data bytes
  205. * @exception IllegalArgumentException if the length of the specified
  206. * extra field data is greater than 0xFFFFF bytes
  207. * @see #getExtra()
  208. */
  209. public void setExtra(byte[] extra) {
  210. if (extra != null && extra.length > 0xFFFF) {
  211. throw new IllegalArgumentException("invalid extra field length");
  212. }
  213. this.extra = extra;
  214. }
  215. /**
  216. * Returns the extra field data for the entry, or null if none.
  217. * @return the extra field data for the entry, or null if none
  218. * @see #setExtra(byte[])
  219. */
  220. public byte[] getExtra() {
  221. return extra;
  222. }
  223. /**
  224. * Sets the optional comment string for the entry.
  225. * @param comment the comment string
  226. * @exception IllegalArgumentException if the length of the specified
  227. * comment string is greater than 0xFFFF bytes
  228. * @see #getComment()
  229. */
  230. public void setComment(String comment) {
  231. if (comment != null && comment.length() > 0xFFFF) {
  232. throw new IllegalArgumentException("invalid entry comment length");
  233. }
  234. this.comment = comment;
  235. }
  236. /**
  237. * Returns the comment string for the entry, or null if none.
  238. * @return the comment string for the entry, or null if none
  239. * @see #setComment(String)
  240. */
  241. public String getComment() {
  242. return comment;
  243. }
  244. /**
  245. * Returns true if this is a directory entry. A directory entry is
  246. * defined to be one whose name ends with a '/'.
  247. * @return true if this is a directory entry
  248. */
  249. public boolean isDirectory() {
  250. return name.endsWith("/");
  251. }
  252. /**
  253. * Returns a string representation of the ZIP entry.
  254. */
  255. public String toString() {
  256. return getName();
  257. }
  258. /*
  259. * Converts DOS time to Java time (number of milliseconds since epoch).
  260. */
  261. private static long dosToJavaTime(long dtime) {
  262. Date d = new Date((int)(((dtime >> 25) & 0x7f) + 80),
  263. (int)(((dtime >> 21) & 0x0f) - 1),
  264. (int)((dtime >> 16) & 0x1f),
  265. (int)((dtime >> 11) & 0x1f),
  266. (int)((dtime >> 5) & 0x3f),
  267. (int)((dtime << 1) & 0x3e));
  268. return d.getTime();
  269. }
  270. /*
  271. * Converts Java time to DOS time.
  272. */
  273. private static long javaToDosTime(long time) {
  274. Date d = new Date(time);
  275. int year = d.getYear() + 1900;
  276. if (year < 1980) {
  277. return (1 << 21) | (1 << 16);
  278. }
  279. return (year - 1980) << 25 | (d.getMonth() + 1) << 21 |
  280. d.getDate() << 16 | d.getHours() << 11 | d.getMinutes() << 5 |
  281. d.getSeconds() >> 1;
  282. }
  283. /**
  284. * Returns the hash code value for this entry.
  285. */
  286. public int hashCode() {
  287. return name.hashCode();
  288. }
  289. /**
  290. * Returns a copy of this entry.
  291. */
  292. public Object clone() {
  293. try {
  294. ZipEntry e = (ZipEntry)super.clone();
  295. e.extra = (extra == null ? null : (byte[])extra.clone());
  296. return e;
  297. } catch (CloneNotSupportedException e) {
  298. // This should never happen, since we are Cloneable
  299. throw new InternalError();
  300. }
  301. }
  302. }