You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

Get.java 15 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. /*
  2. * The Apache Software License, Version 1.1
  3. *
  4. * Copyright (c) 2000-2002 The Apache Software Foundation. All rights
  5. * reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. *
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in
  16. * the documentation and/or other materials provided with the
  17. * distribution.
  18. *
  19. * 3. The end-user documentation included with the redistribution, if
  20. * any, must include the following acknowlegement:
  21. * "This product includes software developed by the
  22. * Apache Software Foundation (http://www.apache.org/)."
  23. * Alternately, this acknowlegement may appear in the software itself,
  24. * if and wherever such third-party acknowlegements normally appear.
  25. *
  26. * 4. The names "The Jakarta Project", "Ant", and "Apache Software
  27. * Foundation" must not be used to endorse or promote products derived
  28. * from this software without prior written permission. For written
  29. * permission, please contact apache@apache.org.
  30. *
  31. * 5. Products derived from this software may not be called "Apache"
  32. * nor may "Apache" appear in their names without prior written
  33. * permission of the Apache Group.
  34. *
  35. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  36. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  37. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  38. * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  39. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  41. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  42. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  43. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  44. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  45. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  46. * SUCH DAMAGE.
  47. * ====================================================================
  48. *
  49. * This software consists of voluntary contributions made by many
  50. * individuals on behalf of the Apache Software Foundation. For more
  51. * information on the Apache Software Foundation, please see
  52. * <http://www.apache.org/>.
  53. */
  54. package org.apache.tools.ant.taskdefs;
  55. import java.io.File;
  56. import java.io.FileOutputStream;
  57. import java.io.InputStream;
  58. import java.io.IOException;
  59. import java.net.URL;
  60. import java.net.URLConnection;
  61. import java.net.HttpURLConnection;
  62. import java.util.Date;
  63. import org.apache.tools.ant.BuildException;
  64. import org.apache.tools.ant.Project;
  65. import org.apache.tools.ant.Task;
  66. import org.apache.tools.ant.util.FileUtils;
  67. import org.apache.tools.ant.util.JavaEnvUtils;
  68. /**
  69. * Get a particular file from a URL source.
  70. * Options include verbose reporting, timestamp based fetches and controlling
  71. * actions on failures. NB: access through a firewall only works if the whole
  72. * Java runtime is correctly configured.
  73. *
  74. * @author costin@dnt.ro
  75. * @author gg@grtmail.com (Added Java 1.1 style HTTP basic auth)
  76. *
  77. * @since Ant 1.1
  78. *
  79. * @ant.task category="network"
  80. */
  81. public class Get extends Task {
  82. private URL source; // required
  83. private File dest; // required
  84. private boolean verbose = false;
  85. private boolean useTimestamp = false; //off by default
  86. private boolean ignoreErrors = false;
  87. private String uname = null;
  88. private String pword = null;
  89. /**
  90. * Does the work.
  91. *
  92. * @exception BuildException Thrown in unrecoverable error.
  93. */
  94. public void execute() throws BuildException {
  95. if (source == null) {
  96. throw new BuildException("src attribute is required", location);
  97. }
  98. if (dest == null) {
  99. throw new BuildException("dest attribute is required", location);
  100. }
  101. if (dest.exists() && dest.isDirectory()) {
  102. throw new BuildException("The specified destination is a directory",
  103. location);
  104. }
  105. if (dest.exists() && !dest.canWrite()) {
  106. throw new BuildException("Can't write to " + dest.getAbsolutePath(),
  107. location);
  108. }
  109. try {
  110. log("Getting: " + source);
  111. //set the timestamp to the file date.
  112. long timestamp = 0;
  113. boolean hasTimestamp = false;
  114. if (useTimestamp && dest.exists()) {
  115. timestamp = dest.lastModified();
  116. if (verbose) {
  117. Date t = new Date(timestamp);
  118. log("local file date : " + t.toString());
  119. }
  120. hasTimestamp = true;
  121. }
  122. //set up the URL connection
  123. URLConnection connection = source.openConnection();
  124. //modify the headers
  125. //NB: things like user authentication could go in here too.
  126. if (useTimestamp && hasTimestamp) {
  127. connection.setIfModifiedSince(timestamp);
  128. }
  129. // prepare Java 1.1 style credentials
  130. if (uname != null || pword != null) {
  131. String up = uname + ":" + pword;
  132. String encoding;
  133. // check to see if sun's Base64 encoder is available.
  134. try {
  135. sun.misc.BASE64Encoder encoder =
  136. (sun.misc.BASE64Encoder)
  137. Class.forName("sun.misc.BASE64Encoder").newInstance();
  138. encoding = encoder.encode (up.getBytes());
  139. } catch (Exception ex) { // sun's base64 encoder isn't available
  140. Base64Converter encoder = new Base64Converter();
  141. encoding = encoder.encode(up.getBytes());
  142. }
  143. connection.setRequestProperty ("Authorization",
  144. "Basic " + encoding);
  145. }
  146. //connect to the remote site (may take some time)
  147. connection.connect();
  148. //next test for a 304 result (HTTP only)
  149. if (connection instanceof HttpURLConnection) {
  150. HttpURLConnection httpConnection
  151. = (HttpURLConnection) connection;
  152. if (httpConnection.getResponseCode()
  153. == HttpURLConnection.HTTP_NOT_MODIFIED) {
  154. //not modified so no file download. just return
  155. //instead and trace out something so the user
  156. //doesn't think that the download happened when it
  157. //didnt
  158. log("Not modified - so not downloaded");
  159. return;
  160. }
  161. // test for 401 result (HTTP only)
  162. if (httpConnection.getResponseCode()
  163. == HttpURLConnection.HTTP_UNAUTHORIZED) {
  164. log("Not authorized - check " + dest + " for details");
  165. return;
  166. }
  167. }
  168. //REVISIT: at this point even non HTTP connections may
  169. //support the if-modified-since behaviour -we just check
  170. //the date of the content and skip the write if it is not
  171. //newer. Some protocols (FTP) dont include dates, of
  172. //course.
  173. FileOutputStream fos = new FileOutputStream(dest);
  174. InputStream is = null;
  175. for (int i = 0; i < 3 ; i++) {
  176. try {
  177. is = connection.getInputStream();
  178. break;
  179. } catch (IOException ex) {
  180. log("Error opening connection " + ex);
  181. }
  182. }
  183. if (is == null) {
  184. log("Can't get " + source + " to " + dest);
  185. if (ignoreErrors) {
  186. return;
  187. }
  188. throw new BuildException("Can't get " + source + " to " + dest,
  189. location);
  190. }
  191. byte[] buffer = new byte[100 * 1024];
  192. int length;
  193. while ((length = is.read(buffer)) >= 0) {
  194. fos.write(buffer, 0, length);
  195. if (verbose) {
  196. System.out.print(".");
  197. }
  198. }
  199. if (verbose) {
  200. System.out.println();
  201. }
  202. fos.close();
  203. is.close();
  204. //if (and only if) the use file time option is set, then
  205. //the saved file now has its timestamp set to that of the
  206. //downloaded file
  207. if (useTimestamp) {
  208. long remoteTimestamp = connection.getLastModified();
  209. if (verbose) {
  210. Date t = new Date(remoteTimestamp);
  211. log("last modified = " + t.toString()
  212. + ((remoteTimestamp == 0)
  213. ? " - using current time instead"
  214. : ""));
  215. }
  216. if (remoteTimestamp != 0) {
  217. FileUtils.newFileUtils()
  218. .setFileLastModified(dest, remoteTimestamp);
  219. }
  220. }
  221. } catch (IOException ioe) {
  222. log("Error getting " + source + " to " + dest);
  223. if (ignoreErrors) {
  224. return;
  225. }
  226. throw new BuildException(ioe, location);
  227. }
  228. }
  229. /**
  230. * Set the URL.
  231. *
  232. * @param u URL for the file.
  233. */
  234. public void setSrc(URL u) {
  235. this.source = u;
  236. }
  237. /**
  238. * Where to copy the source file.
  239. *
  240. * @param dest Path to file.
  241. */
  242. public void setDest(File dest) {
  243. this.dest = dest;
  244. }
  245. /**
  246. * Be verbose, if set to "<CODE>true</CODE>".
  247. *
  248. * @param v if "true" then be verbose
  249. */
  250. public void setVerbose(boolean v) {
  251. verbose = v;
  252. }
  253. /**
  254. * Don't stop if get fails if set to "<CODE>true</CODE>".
  255. *
  256. * @param v if "true" then don't report download errors up to ant
  257. */
  258. public void setIgnoreErrors(boolean v) {
  259. ignoreErrors = v;
  260. }
  261. /**
  262. * Use timestamps, if set to "<CODE>true</CODE>".
  263. *
  264. * <p>In this situation, the if-modified-since header is set so
  265. * that the file is only fetched if it is newer than the local
  266. * file (or there is no local file) This flag is only valid on
  267. * HTTP connections, it is ignored in other cases. When the flag
  268. * is set, the local copy of the downloaded file will also have
  269. * its timestamp set to the remote file time.</p>
  270. *
  271. * <p>Note that remote files of date 1/1/1970 (GMT) are treated as
  272. * 'no timestamp', and web servers often serve files with a
  273. * timestamp in the future by replacing their timestamp with that
  274. * of the current time. Also, inter-computer clock differences can
  275. * cause no end of grief.</p>
  276. * @param v "true" to enable file time fetching
  277. */
  278. public void setUseTimestamp(boolean v) {
  279. if (!JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_1)) {
  280. useTimestamp = v;
  281. }
  282. }
  283. /**
  284. * Username for basic auth.
  285. *
  286. * @param u username for authentication
  287. */
  288. public void setUsername(String u) {
  289. this.uname = u;
  290. }
  291. /**
  292. * password for the basic auth.
  293. *
  294. * @param p password for authentication
  295. */
  296. public void setPassword(String p) {
  297. this.pword = p;
  298. }
  299. /*********************************************************************
  300. * BASE 64 encoding of a String or an array of bytes.
  301. *
  302. * Based on RFC 1421.
  303. *
  304. * @author
  305. * Unknown
  306. * @author
  307. * <a HREF="gg@grtmail.com">Gautam Guliani</a>
  308. *********************************************************************/
  309. class Base64Converter {
  310. public final char [ ] alphabet = {
  311. 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', // 0 to 7
  312. 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', // 8 to 15
  313. 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', // 16 to 23
  314. 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', // 24 to 31
  315. 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', // 32 to 39
  316. 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', // 40 to 47
  317. 'w', 'x', 'y', 'z', '0', '1', '2', '3', // 48 to 55
  318. '4', '5', '6', '7', '8', '9', '+', '/' }; // 56 to 63
  319. public String encode(String s) {
  320. return encode (s.getBytes());
  321. }
  322. public String encode(byte[ ] octetString) {
  323. int bits24;
  324. int bits6;
  325. char [ ] out
  326. = new char[((octetString.length - 1) / 3 + 1) * 4];
  327. int outIndex = 0;
  328. int i = 0;
  329. while ((i + 3) <= octetString.length) {
  330. // store the octets
  331. bits24 = (octetString[i++] & 0xFF) << 16;
  332. bits24 |= (octetString[i++] & 0xFF) << 8;
  333. bits6 = (bits24 & 0x00FC0000) >> 18;
  334. out[outIndex++] = alphabet[bits6];
  335. bits6 = (bits24 & 0x0003F000) >> 12;
  336. out[outIndex++] = alphabet[bits6];
  337. bits6 = (bits24 & 0x00000FC0) >> 6;
  338. out[outIndex++] = alphabet[bits6];
  339. bits6 = (bits24 & 0x0000003F);
  340. out[outIndex++] = alphabet[bits6];
  341. }
  342. if (octetString.length - i == 2) {
  343. // store the octets
  344. bits24 = (octetString[i] & 0xFF) << 16;
  345. bits24 |= (octetString[i + 1] & 0xFF) << 8;
  346. bits6 = (bits24 & 0x00FC0000) >> 18;
  347. out[outIndex++] = alphabet[bits6];
  348. bits6 = (bits24 & 0x0003F000) >> 12;
  349. out[outIndex++] = alphabet[bits6];
  350. bits6 = (bits24 & 0x00000FC0) >> 6;
  351. out[outIndex++] = alphabet[bits6];
  352. // padding
  353. out[outIndex++] = '=';
  354. } else if (octetString.length - i == 1) {
  355. // store the octets
  356. bits24 = (octetString[i] & 0xFF) << 16;
  357. bits6 = (bits24 & 0x00FC0000) >> 18;
  358. out[outIndex++] = alphabet[bits6];
  359. bits6 = (bits24 & 0x0003F000) >> 12;
  360. out[outIndex++] = alphabet[ bits6 ];
  361. // padding
  362. out[outIndex++] = '=';
  363. out[outIndex++] = '=';
  364. }
  365. return new String(out);
  366. }
  367. }
  368. }