PageRenderTime 47ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 1ms

/java-1.7.0-openjdk/openjdk/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipUtils.java

#
Java | 320 lines | 217 code | 23 blank | 80 comment | 54 complexity | de6ed37e3a3691410836a578400d0356 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause-No-Nuclear-License-2014, LGPL-3.0, LGPL-2.0
  1. /*
  2. * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * - Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. *
  11. * - Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. *
  15. * - Neither the name of Oracle nor the names of its
  16. * contributors may be used to endorse or promote products derived
  17. * from this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
  20. * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  21. * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  22. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  23. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  24. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  25. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  26. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  27. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  28. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  29. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. */
  31. /*
  32. * This source code is provided to illustrate the usage of a given feature
  33. * or technique and has been deliberately simplified. Additional steps
  34. * required for a production-quality application, such as security checks,
  35. * input validation and proper error handling, might not be present in
  36. * this sample code.
  37. */
  38. package com.sun.nio.zipfs;
  39. import java.io.IOException;
  40. import java.io.OutputStream;
  41. import java.util.Arrays;
  42. import java.util.Date;
  43. import java.util.regex.PatternSyntaxException;
  44. import java.util.concurrent.TimeUnit;
  45. /**
  46. *
  47. * @author Xueming Shen
  48. */
  49. class ZipUtils {
  50. /*
  51. * Writes a 16-bit short to the output stream in little-endian byte order.
  52. */
  53. public static void writeShort(OutputStream os, int v) throws IOException {
  54. os.write(v & 0xff);
  55. os.write((v >>> 8) & 0xff);
  56. }
  57. /*
  58. * Writes a 32-bit int to the output stream in little-endian byte order.
  59. */
  60. public static void writeInt(OutputStream os, long v) throws IOException {
  61. os.write((int)(v & 0xff));
  62. os.write((int)((v >>> 8) & 0xff));
  63. os.write((int)((v >>> 16) & 0xff));
  64. os.write((int)((v >>> 24) & 0xff));
  65. }
  66. /*
  67. * Writes a 64-bit int to the output stream in little-endian byte order.
  68. */
  69. public static void writeLong(OutputStream os, long v) throws IOException {
  70. os.write((int)(v & 0xff));
  71. os.write((int)((v >>> 8) & 0xff));
  72. os.write((int)((v >>> 16) & 0xff));
  73. os.write((int)((v >>> 24) & 0xff));
  74. os.write((int)((v >>> 32) & 0xff));
  75. os.write((int)((v >>> 40) & 0xff));
  76. os.write((int)((v >>> 48) & 0xff));
  77. os.write((int)((v >>> 56) & 0xff));
  78. }
  79. /*
  80. * Writes an array of bytes to the output stream.
  81. */
  82. public static void writeBytes(OutputStream os, byte[] b)
  83. throws IOException
  84. {
  85. os.write(b, 0, b.length);
  86. }
  87. /*
  88. * Writes an array of bytes to the output stream.
  89. */
  90. public static void writeBytes(OutputStream os, byte[] b, int off, int len)
  91. throws IOException
  92. {
  93. os.write(b, off, len);
  94. }
  95. /*
  96. * Append a slash at the end, if it does not have one yet
  97. */
  98. public static byte[] toDirectoryPath(byte[] dir) {
  99. if (dir.length != 0 && dir[dir.length - 1] != '/') {
  100. dir = Arrays.copyOf(dir, dir.length + 1);
  101. dir[dir.length - 1] = '/';
  102. }
  103. return dir;
  104. }
  105. /*
  106. * Converts DOS time to Java time (number of milliseconds since epoch).
  107. */
  108. public static long dosToJavaTime(long dtime) {
  109. Date d = new Date((int)(((dtime >> 25) & 0x7f) + 80),
  110. (int)(((dtime >> 21) & 0x0f) - 1),
  111. (int)((dtime >> 16) & 0x1f),
  112. (int)((dtime >> 11) & 0x1f),
  113. (int)((dtime >> 5) & 0x3f),
  114. (int)((dtime << 1) & 0x3e));
  115. return d.getTime();
  116. }
  117. /*
  118. * Converts Java time to DOS time.
  119. */
  120. public static long javaToDosTime(long time) {
  121. Date d = new Date(time);
  122. int year = d.getYear() + 1900;
  123. if (year < 1980) {
  124. return (1 << 21) | (1 << 16);
  125. }
  126. return (year - 1980) << 25 | (d.getMonth() + 1) << 21 |
  127. d.getDate() << 16 | d.getHours() << 11 | d.getMinutes() << 5 |
  128. d.getSeconds() >> 1;
  129. }
  130. // used to adjust values between Windows and java epoch
  131. private static final long WINDOWS_EPOCH_IN_MICROSECONDS = -11644473600000000L;
  132. public static final long winToJavaTime(long wtime) {
  133. return TimeUnit.MILLISECONDS.convert(
  134. wtime / 10 + WINDOWS_EPOCH_IN_MICROSECONDS, TimeUnit.MICROSECONDS);
  135. }
  136. public static final long javaToWinTime(long time) {
  137. return (TimeUnit.MICROSECONDS.convert(time, TimeUnit.MILLISECONDS)
  138. - WINDOWS_EPOCH_IN_MICROSECONDS) * 10;
  139. }
  140. public static final long unixToJavaTime(long utime) {
  141. return TimeUnit.MILLISECONDS.convert(utime, TimeUnit.SECONDS);
  142. }
  143. public static final long javaToUnixTime(long time) {
  144. return TimeUnit.SECONDS.convert(time, TimeUnit.MILLISECONDS);
  145. }
  146. private static final String regexMetaChars = ".^$+{[]|()";
  147. private static final String globMetaChars = "\\*?[{";
  148. private static boolean isRegexMeta(char c) {
  149. return regexMetaChars.indexOf(c) != -1;
  150. }
  151. private static boolean isGlobMeta(char c) {
  152. return globMetaChars.indexOf(c) != -1;
  153. }
  154. private static char EOL = 0; //TBD
  155. private static char next(String glob, int i) {
  156. if (i < glob.length()) {
  157. return glob.charAt(i);
  158. }
  159. return EOL;
  160. }
  161. /*
  162. * Creates a regex pattern from the given glob expression.
  163. *
  164. * @throws PatternSyntaxException
  165. */
  166. public static String toRegexPattern(String globPattern) {
  167. boolean inGroup = false;
  168. StringBuilder regex = new StringBuilder("^");
  169. int i = 0;
  170. while (i < globPattern.length()) {
  171. char c = globPattern.charAt(i++);
  172. switch (c) {
  173. case '\\':
  174. // escape special characters
  175. if (i == globPattern.length()) {
  176. throw new PatternSyntaxException("No character to escape",
  177. globPattern, i - 1);
  178. }
  179. char next = globPattern.charAt(i++);
  180. if (isGlobMeta(next) || isRegexMeta(next)) {
  181. regex.append('\\');
  182. }
  183. regex.append(next);
  184. break;
  185. case '/':
  186. regex.append(c);
  187. break;
  188. case '[':
  189. // don't match name separator in class
  190. regex.append("[[^/]&&[");
  191. if (next(globPattern, i) == '^') {
  192. // escape the regex negation char if it appears
  193. regex.append("\\^");
  194. i++;
  195. } else {
  196. // negation
  197. if (next(globPattern, i) == '!') {
  198. regex.append('^');
  199. i++;
  200. }
  201. // hyphen allowed at start
  202. if (next(globPattern, i) == '-') {
  203. regex.append('-');
  204. i++;
  205. }
  206. }
  207. boolean hasRangeStart = false;
  208. char last = 0;
  209. while (i < globPattern.length()) {
  210. c = globPattern.charAt(i++);
  211. if (c == ']') {
  212. break;
  213. }
  214. if (c == '/') {
  215. throw new PatternSyntaxException("Explicit 'name separator' in class",
  216. globPattern, i - 1);
  217. }
  218. // TBD: how to specify ']' in a class?
  219. if (c == '\\' || c == '[' ||
  220. c == '&' && next(globPattern, i) == '&') {
  221. // escape '\', '[' or "&&" for regex class
  222. regex.append('\\');
  223. }
  224. regex.append(c);
  225. if (c == '-') {
  226. if (!hasRangeStart) {
  227. throw new PatternSyntaxException("Invalid range",
  228. globPattern, i - 1);
  229. }
  230. if ((c = next(globPattern, i++)) == EOL || c == ']') {
  231. break;
  232. }
  233. if (c < last) {
  234. throw new PatternSyntaxException("Invalid range",
  235. globPattern, i - 3);
  236. }
  237. regex.append(c);
  238. hasRangeStart = false;
  239. } else {
  240. hasRangeStart = true;
  241. last = c;
  242. }
  243. }
  244. if (c != ']') {
  245. throw new PatternSyntaxException("Missing ']", globPattern, i - 1);
  246. }
  247. regex.append("]]");
  248. break;
  249. case '{':
  250. if (inGroup) {
  251. throw new PatternSyntaxException("Cannot nest groups",
  252. globPattern, i - 1);
  253. }
  254. regex.append("(?:(?:");
  255. inGroup = true;
  256. break;
  257. case '}':
  258. if (inGroup) {
  259. regex.append("))");
  260. inGroup = false;
  261. } else {
  262. regex.append('}');
  263. }
  264. break;
  265. case ',':
  266. if (inGroup) {
  267. regex.append(")|(?:");
  268. } else {
  269. regex.append(',');
  270. }
  271. break;
  272. case '*':
  273. if (next(globPattern, i) == '*') {
  274. // crosses directory boundaries
  275. regex.append(".*");
  276. i++;
  277. } else {
  278. // within directory boundary
  279. regex.append("[^/]*");
  280. }
  281. break;
  282. case '?':
  283. regex.append("[^/]");
  284. break;
  285. default:
  286. if (isRegexMeta(c)) {
  287. regex.append('\\');
  288. }
  289. regex.append(c);
  290. }
  291. }
  292. if (inGroup) {
  293. throw new PatternSyntaxException("Missing '}", globPattern, i - 1);
  294. }
  295. return regex.append('$').toString();
  296. }
  297. }