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