001package arcommon.net; 002 003import java.awt.Desktop; 004import java.awt.Dialog; 005import java.awt.Frame; 006import java.awt.KeyboardFocusManager; 007import java.awt.Window; 008import java.awt.event.ActionEvent; 009import java.awt.event.ActionListener; 010import java.awt.event.WindowAdapter; 011import java.awt.event.WindowEvent; 012import java.io.BufferedReader; 013import java.io.DataInputStream; 014import java.io.File; 015import java.io.FileOutputStream; 016import java.io.IOException; 017import java.io.InputStreamReader; 018import java.io.StringReader; 019import java.io.UnsupportedEncodingException; 020import java.net.HttpURLConnection; 021import java.net.IDN; 022import java.net.MalformedURLException; 023import java.net.URI; 024import java.net.URISyntaxException; 025import java.net.URL; 026import java.net.URLDecoder; 027import java.net.URLEncoder; 028import java.security.NoSuchAlgorithmException; 029import java.security.cert.CertificateException; 030import java.security.cert.X509Certificate; 031 032import javax.crypto.Cipher; 033import javax.net.ssl.HttpsURLConnection; 034import javax.net.ssl.SSLContext; 035import javax.net.ssl.TrustManager; 036import javax.net.ssl.X509TrustManager; 037import javax.swing.JDialog; 038import javax.swing.JLabel; 039import javax.swing.SwingUtilities; 040import javax.swing.text.html.HTMLDocument; 041import javax.swing.text.html.HTMLEditorKit; 042 043import arcommon.ArrayUtil; 044import arcommon.FileUtil; 045import arcommon.MyTimer; 046import arcommon.StringUtil; 047import arcommon.progress.ProgressState; 048import arcommon.progress.ProgressThreadData; 049import arcommon.ui.other.GUIUtil; 050 051public class NetUtil { 052 public static final String EMAIL_PROTOCOL = "mailto:"; 053 public static final String PHONE_PROTOCOL = "tel:"; 054 055 // WARNING: This seems to break stuff 056/* public static void setDefaultHostnameVerifier() { 057 HostnameVerifier hostnameVerifier = new HostnameVerifier() { 058 public boolean verify(String urlHostName, SSLSession session) { 059 System.out.println("Warning: URL Host: \"" + urlHostName + "\" vs \"" + session.getPeerHost() + "\""); 060 return true; 061 } 062 }; 063 HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier); 064 }*/ 065 066 public static void trustAllHttpsCertificates() { 067 try { 068 // Create a trust manager that does not validate certificate chains: 069 TrustManager[] trustAllCertificates = new TrustManager[1]; 070 071 TrustManager trustManager = new MyTrustManager(); 072 073 trustAllCertificates[0] = trustManager; 074 075 SSLContext sslContext = SSLContext.getInstance("SSL"); 076 077 sslContext.init(null, trustAllCertificates, null); 078 079 HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory()); 080 } catch (Exception e) { 081 throw new RuntimeException(e); 082 } 083 } 084 085 public static void checkUnlimitedCipher() { 086 try { 087 int maximumKeyLength = Cipher.getMaxAllowedKeyLength("AES"); 088 if (maximumKeyLength <= 128) { 089 throw new RuntimeException("maximumKeyLength <= 128 " + maximumKeyLength); 090 } 091 } catch (NoSuchAlgorithmException e) { 092 throw new RuntimeException(e); 093 } 094 } 095 096 private static class MyTrustManager implements TrustManager, X509TrustManager { 097 public X509Certificate[] getAcceptedIssuers() { 098 return null; 099 } 100 101 public void checkServerTrusted(X509Certificate[] certificates, String authType) throws CertificateException { 102 return ; 103 } 104 105 public void checkClientTrusted(X509Certificate[] certificates, String authType) throws CertificateException { 106 return ; 107 } 108 } 109 110 private static JDialog jDialog; 111 private static ActionListener actionListener; 112 113 private static void removeTimerAndDialog() { 114 if (jDialog != null) { 115 jDialog.dispose(); 116 jDialog = null; 117 } 118 119 if (actionListener != null) { 120 MyTimer.removeActionListener(actionListener); 121 } 122 actionListener = null; 123 } 124 125 public static void openBrowserWithDialog(final String url) { 126 boolean dialogCreated = false; 127 if (jDialog == null) { 128 Window activeWindow = KeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow(); 129 if (activeWindow instanceof Frame) { 130 Frame frame = (Frame)activeWindow; 131 jDialog = new JDialog(frame) { 132 private static final long serialVersionUID = 3519454107167020418L; 133 @Override 134 public void dispose() { 135 super.dispose(); 136 jDialog = null; 137 removeTimerAndDialog(); 138 } 139 }; 140 } else { 141 Dialog dialog = (Dialog)activeWindow; 142 jDialog = new JDialog(dialog) { 143 private static final long serialVersionUID = -5025589815908734974L; 144 145 @Override 146 public void dispose() { 147 super.dispose(); 148 jDialog = null; 149 removeTimerAndDialog(); 150 } 151 }; 152 } 153 154 jDialog.setTitle("Opening URL..."); 155 jDialog.getContentPane().add(new JLabel("Please wait while link is opened")); 156 jDialog.setResizable(false); 157 jDialog.pack(); 158 jDialog.setModal(true); 159 GUIUtil.centerOnParent(jDialog); 160 161 jDialog.addWindowFocusListener(new WindowAdapter() { 162 public void windowLostFocus(WindowEvent e) { 163 removeTimerAndDialog(); 164 } 165 }); 166 167 dialogCreated = true; 168 } 169 170 if (actionListener == null) { 171 actionListener = new ActionListener() { 172 @Override 173 public void actionPerformed(ActionEvent event) { 174 SwingUtilities.invokeLater(new Runnable() { 175 public void run() { 176 removeTimerAndDialog(); 177 } 178 }); 179 } 180 }; 181 MyTimer.addActionListener(100, actionListener); 182 } 183 184 final boolean dialogCreatedFinal = dialogCreated; 185 SwingUtilities.invokeLater(new Runnable() { 186 public void run() { 187 if (jDialog != null && dialogCreatedFinal) { 188 jDialog.setVisible(true); 189 } 190 } 191 }); 192 193 SwingUtilities.invokeLater(new Runnable() { 194 public void run() { 195 try { 196 boolean ok = openBrowser(url); 197 if (!ok && jDialog != null) { 198 jDialog.dispose(); 199 jDialog = null; 200 } 201 } catch (Exception e) { 202 if (jDialog != null) { 203 jDialog.dispose(); 204 jDialog = null; 205 } 206 throw new RuntimeException(e); 207 } 208 } 209 }); 210 } 211 212 public static boolean openBrowser(String url) { 213 URI uri; 214 if (FileUtil.exists(url)) { 215 uri = new File(url).toURI(); 216 } else { 217 try { 218 uri = new URI(url); 219 } catch (URISyntaxException e) { 220 try { 221 url = encodeUrlMyVariant(url); 222 uri = new URI(url); 223 } catch (URISyntaxException e2) { 224 throw new RuntimeException(e2); 225 } 226 } 227 } 228 Desktop desktop = Desktop.getDesktop(); 229 try { 230 desktop.browse(uri); 231 return true; 232 } catch (IOException e) { 233 if (e != null && e.getMessage() != null && e.getMessage().startsWith("Failed to show URI")) { 234 GUIUtil.showErrorMessage("Failed to show url \"" + decodeUrlToDisplayString(url) + "\"\n(\"" + url + "\")"); 235 return false; 236 } 237 throw new RuntimeException(e); 238 } 239 } 240 241 /** 242 * Returns true if the url parameter is a valid URL. 243 * <br> 244 * Note: This method will return true on phone numbers (tel:) even though new URL("tel:+45%2020") will throw a MalformedURLException. 245 */ 246 public static boolean isUrlValid(String url) { 247 try { 248 if (url == null) { 249 return false; 250 } 251 new URI(url); 252 return true; 253 } catch (URISyntaxException e) { 254 return false; 255 } 256 } 257 258 /** 259 * This method will return the urlString parameter URL in a displayable / human-readable format. 260 * <br> 261 * Note: E-mails (mailto:) and phone numbers (tel:) will be "displayed" (=returned) without protocol.<br> 262 * Note: This is not the (complete) reversed function of {@link #encodeUrlMyVariant(String)}<br> 263 * encodeUrlMyVariant(decodeUrlToDisplayString(urlString)) != urlString 264 * @see #decodeCookieElement(String) 265 * @see #decodeUrlPath(String) 266 * @see #encodeUrlFormData(String) 267 * @see #encodeUrlPath(String) 268 * @see #encodeUrlMyVariant(String) 269 * @see arcommon.xml.XmlUtil#encodeXmlString(String) 270 * @see arcommon.xml.XmlUtil#decodeXmlString(String) 271 */ 272 public static String decodeUrlToDisplayString(String urlString) { 273 if (urlString == null) { 274 return null; 275 } 276 277 if (urlString.startsWith(EMAIL_PROTOCOL)) { 278 urlString = urlString.substring(EMAIL_PROTOCOL.length()); 279 return decodeUrlPath(urlString); 280 } 281 282 if (urlString.startsWith(PHONE_PROTOCOL)) { 283 urlString = urlString.substring(PHONE_PROTOCOL.length()); 284 return decodeUrlPath(urlString); 285 } 286 287 try { 288 URL url = new URL(urlString); 289 290 String host = url.getHost(); 291 int indexOf = urlString.indexOf(host); 292 if (indexOf == -1) { 293 throw new RuntimeException("indexOf == -1 " + host + " " + url); 294 } 295 String result = urlString.substring(0, indexOf); 296 297 result += decodeDomainNameFromIDN(host); 298 299 String path = url.getPath(); 300 if (path != null) { 301 result += decodeUrlPath(path); 302 } 303 304 String query = url.getQuery(); 305 if (query != null) { 306 result += "?" + decodeUrlFormData(query); 307 } 308 309 String ref = url.getRef(); 310 if (ref != null) { 311 result += "#" + ref; 312 } 313 314 return result; 315 } catch (MalformedURLException e) { 316 return urlString + " (INVALID!! " + e.getMessage() + ")"; 317 } 318 } 319 320 /** 321 * @see #encodeDomainNameToIDN(String) 322 */ 323 public static String decodeDomainNameFromIDN(String domainName) { 324 String[] domainNameSplit = domainName.split("\\."); 325 String result = ""; 326 for (int i = 0; i < domainNameSplit.length; i++) { 327 if (result.length() > 0) { 328 result += "."; 329 } 330 String string = domainNameSplit[i]; 331 result += IDN.toUnicode(string); 332 } 333 return result; 334 } 335 336 /** 337 * @see #decodeUrlToDisplayString(String) see decodeUrlToDisplayString because it is probably the method you want 338 * @see #decodeUrlPath(String) 339 * @see #encodeUrlFormData(String) 340 * @see #encodeUrlPath(String) 341 * @see #encodeUrlMyVariant(String) 342 * @see arcommon.xml.XmlUtil#encodeXmlString(String) 343 * @see arcommon.xml.XmlUtil#decodeXmlString(String) 344 */ 345 public static String decodeUrlFormData(String url) { 346 try { 347 return URLDecoder.decode(url, "UTF-8"); 348 } catch (UnsupportedEncodingException e) { 349 throw new RuntimeException(e); 350 } 351 } 352 353 /** 354 * @see #decodeUrlToDisplayString(String) see decodeUrlToDisplayString because it is probably the method you want 355 * @see #decodeUrlFormData(String) 356 * @see #encodeUrlFormData(String) 357 * @see #encodeUrlPath(String) 358 * @see #encodeUrlMyVariant(String) 359 * @see arcommon.xml.XmlUtil#encodeXmlString(String) 360 * @see arcommon.xml.XmlUtil#decodeXmlString(String) 361 */ 362 public static String decodeUrlPath(String url) { 363 try { 364 return new URI(url).getPath(); 365 } catch (URISyntaxException e) { 366 throw new RuntimeException(e); 367 } 368 } 369 370 private static final String VALID_URL_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~:/[]@!$&'()*,;`.?#=+"; 371 private static final String VALID_URL_ENCODE_CHARS = "ABCDEF0123456789abcde"; 372 private enum Mode {PROTOCOL, DOMAIN, PATH, FORM}; 373 private static final int MAX_DOMAIN_NAME_LENGTH = 63; // See private IDN.MAX_LABEL_LENGTH 374 375 /** 376 * This method will return the encoding the entire URL (if needed). 377 * <br> 378 * This method is "stable" e.g. it can be called on it own return value without any change:<br> 379 * encodeUrlMyVariant(url) == encodeUrlMyVariant(encodeUrlMyVariant(url)) 380 * @see #encodeUrlFormData(String) see encodeUrlFormData for a method that will encode parts of the URL 381 * @see #encodeUrlPath(String) see encodeUrlPath for a method that will encode parts of the URL 382 * @see #decodeUrlFormData(String) 383 * @see #decodeUrlPath(String) 384 * @see #decodeUrlToDisplayString(String) 385 * @see arcommon.xml.XmlUtil#encodeXmlString(String) 386 * @see arcommon.xml.XmlUtil#decodeXmlString(String) 387 */ 388 public static String encodeUrlMyVariant(String url) { 389 StringBuilder stringBuilder = new StringBuilder(); 390 boolean domainMostBeIdnEncoded = false; 391 int domainStartIndex = 0; 392 int protocolIndex = url.indexOf(':'); 393 boolean protocolFound = protocolIndex != -1 && protocolIndex < 10; 394 Mode mode = protocolFound ? Mode.PROTOCOL : Mode.PATH; 395 for (int i = 0; i < url.length(); i++) { 396 char c = url.charAt(i); 397 398 if (c == '#') { // Anchor should not be encoded; 399 stringBuilder.append(url.substring(i)); 400 break; 401 } 402 403 if ((mode == Mode.PATH || mode == Mode.FORM) && c == '%' && i + 2 < url.length() && VALID_URL_ENCODE_CHARS.contains(url.substring(i + 1, i + 2)) && VALID_URL_ENCODE_CHARS.contains(url.substring(i + 2, i + 3))) { 404 stringBuilder.append(url.substring(i, i + 3).toUpperCase()); 405 i += 2; 406 continue; 407 } 408 409 if (c == ':' && mode == Mode.PROTOCOL) { 410 if (url.startsWith(PHONE_PROTOCOL)) { 411 mode = Mode.PATH; // Hack to make "tel:" be encoded by encodeUrlPath 412 } else { 413 mode = Mode.DOMAIN; 414 domainStartIndex = i; 415 } 416 } 417 418 if ((c == '/' || stringBuilder.length() >= MAX_DOMAIN_NAME_LENGTH) && mode == Mode.DOMAIN) { 419 if (domainStartIndex == i - 1) { 420 domainStartIndex = i; 421 } else { 422 if (domainMostBeIdnEncoded) { 423 stringBuilder = encodeDomainName(stringBuilder, domainStartIndex); 424 domainMostBeIdnEncoded = false; 425 } 426 mode = Mode.PATH; 427 } 428 } 429 430 if (c == '?' && (mode == Mode.PATH || mode == Mode.DOMAIN)) { 431 stringBuilder.append(c); 432 mode = Mode.FORM; 433 continue; 434 } 435 436 int index = VALID_URL_CHARS.indexOf(c); 437 if (index != -1) { 438 // Character is valid 439 stringBuilder.append(c); 440 continue; 441 } 442 443 // Character c is not valid 444 String encoded; 445 switch (mode) { 446 case DOMAIN : 447 encoded = "" + c; 448 domainMostBeIdnEncoded = true; 449 break; 450 case PATH : 451 encoded = encodeUrlPath("/" + c); 452 encoded = encoded.substring(1); 453 break; 454 case FORM : 455 encoded = encodeUrlFormData("" + c); 456 break; 457 case PROTOCOL : 458 throw new RuntimeException("Invalid char in protocol: '" + c + "' " + i + " \"" + url + "\" \"" + stringBuilder); 459 default : 460 throw new RuntimeException("Unknown mode: " + mode + " \"" + url + "\" \"" + stringBuilder); 461 } 462 stringBuilder.append(encoded); 463 } 464 465 if (domainMostBeIdnEncoded) { 466 stringBuilder = encodeDomainName(stringBuilder, domainStartIndex); 467 domainMostBeIdnEncoded = false; 468 } 469 470 return stringBuilder.toString(); 471 } 472 473 private static StringBuilder encodeDomainName(StringBuilder stringBuilder, int domainStartIndex) { 474 String string = stringBuilder.toString(); 475 String protocol = string.substring(0, domainStartIndex + 1); 476 String domainName = string.substring(domainStartIndex + 1); 477 String domainNameInIDN = encodeDomainNameToIDN(domainName); 478 stringBuilder = new StringBuilder(protocol + domainNameInIDN); 479 return stringBuilder; 480 } 481 482 /** 483 * @see #decodeDomainNameFromIDN 484 */ 485 public static String encodeDomainNameToIDN(String domainName) { 486 return IDN.toASCII(domainName); 487 } 488 489 /** 490 * This will encode ' ' as '+' and that will properly not work, if it is used before the '?' in the URL. 491 * @see #encodeUrlPath see encodeUrlPath for a method that encodes ' ' as "%20" which will properly not work, if it is used after the '?' 492 * @see #encodeUrlMyVariant see encodeUrlMyVariant for a method that will encode the entire URL (if needed) 493 * @see #decodeUrlFormData(String) 494 * @see #decodeUrlPath(String) 495 * @see #decodeUrlToDisplayString(String) 496 * @see arcommon.xml.XmlUtil#encodeXmlString(String) 497 * @see arcommon.xml.XmlUtil#decodeXmlString(String) 498 */ 499 public static String encodeUrlFormData(String url) { 500 try { 501 return URLEncoder.encode(url, "UTF-8"); 502 } catch (UnsupportedEncodingException e) { 503 throw new RuntimeException(e); 504 } 505 } 506 507 // Code copied from https://stackoverflow.com/questions/10786042/java-url-encoding-of-query-string-parameters 508 // and modified beyond recognition 509 /** 510 * This will encode ' ' as "%20" and that will properly not work, if it is used after the '?' in the URL. 511 * @see #encodeUrlFormData see encodeUrlFormData for a method that encodes ' ' as '+' which will properly not work, if it is used before the '?' 512 * @see #encodeUrlMyVariant see encodeUrlMyVariant for a method that will encode the entire URL (if needed) 513 * @see #decodeUrlFormData(String) 514 * @see #decodeUrlPath(String) 515 * @see #decodeUrlToDisplayString(String) 516 * @see arcommon.xml.XmlUtil#encodeXmlString(String) 517 * @see arcommon.xml.XmlUtil#decodeXmlString(String) 518 */ 519 public static String encodeUrlPath(String path) { 520 if (path == null) { 521 throw new NullPointerException("path == null"); 522 } 523 if (path.isEmpty()) { 524 throw new NullPointerException("path.isEmpty()"); 525 } 526 try { 527 URI uri = new URI(null, null, null, -1, path, null, null); 528 String encodedPath = uri.toASCIIString(); 529 return encodedPath; 530 } catch (URISyntaxException e) { 531 throw new RuntimeException(e); 532 } 533 } 534 535 // See https://stackoverflow.com/questions/1969232/what-are-allowed-characters-in-cookies/1969339#1969339 536 private static final String VALID_COOKIE_NAME_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!#$&'*+-.^_`|~"; 537 private static final String VALID_COOKIE_VALUE_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!#$&'()*+-./:<=>?@[]^_`{|}~"; 538 539 // See https://stackoverflow.com/questions/1969232/what-are-allowed-characters-in-cookies/1969339#1969339 540 public static String decodeCookieElement(String cookieElement) { 541// return decodeUrlPath(cookieElement); // This can't be used as it will not decode after the '#' character 542 StringBuilder stringBuilder = new StringBuilder(); 543 byte[] bytes = new byte[cookieElement.length() * 4]; 544 int byteIndex = 0; 545 for (int i = 0; i < cookieElement.length(); i++) { 546 char c = cookieElement.charAt(i); 547 if (c != '%') { 548 decodeCookieElementAppend(stringBuilder, bytes, byteIndex); 549 byteIndex = 0; 550 551 stringBuilder.append(c); 552 continue; 553 } 554 555 if (i + 2 >= cookieElement.length()) { 556 throw new RuntimeException("i + 2 >= cookieElement.length() " + i + " " + cookieElement); 557 } 558 559// bytes[byteIndex++] = Byte.parseByte(cookieElement.substring(i + 1, i + 3), 16); // This can't used here as values above 127 can't be handled by Byte.parseByte(). The code below will make them negative (-). 560 int high = ArrayUtil.indexOf(StringUtil.HEX, cookieElement.charAt(i + 1)); 561 int low = ArrayUtil.indexOf(StringUtil.HEX, cookieElement.charAt(i + 2)); 562 bytes[byteIndex++] = (byte)(high * 16 + low - 256); 563 i += 2; 564 } 565 566 decodeCookieElementAppend(stringBuilder, bytes, byteIndex); 567 568 return stringBuilder.toString(); 569 } 570 571 private static void decodeCookieElementAppend(StringBuilder stringBuilder, byte[] bytes, int byteIndex) { 572 if (byteIndex == 0) { 573 return ; 574 } 575 576 try { 577 String string = new String(bytes, 0, byteIndex, "UTF-8"); 578 stringBuilder.append(string); 579 } catch (UnsupportedEncodingException e) { 580 throw new RuntimeException(e); 581 } 582 } 583 584 // See https://stackoverflow.com/questions/1969232/what-are-allowed-characters-in-cookies/1969339#1969339 585 public static String encodeCookieName(String cookieName) { 586 return encodeCookieElement(cookieName, VALID_COOKIE_NAME_CHARS); 587 } 588 589 // See https://stackoverflow.com/questions/1969232/what-are-allowed-characters-in-cookies/1969339#1969339 590 public static String encodeCookieValue(String cookieValue) { 591 return encodeCookieElement(cookieValue, VALID_COOKIE_VALUE_CHARS); 592 } 593 594 // See https://stackoverflow.com/questions/1969232/what-are-allowed-characters-in-cookies/1969339#1969339 595 private static String encodeCookieElement(String cookieElement, String validChars) { 596 StringBuilder stringBuilder = new StringBuilder(); 597 for (int i = 0; i < cookieElement.length(); i++) { 598 char c = cookieElement.charAt(i); 599 600 int index = validChars.indexOf(c); 601 if (index != -1) { 602 // Character is valid 603 stringBuilder.append(c); 604 continue; 605 } 606 607 // Character c is not valid 608 // encodeUrlPath("/" + c); // Can't be used here because it will not encode # 609 String encoded = ""; 610 try { 611 byte[] bytes = new String("" + c).getBytes("UTF-8"); 612 for (int j = 0; j < bytes.length; j++) { 613 encoded += "%" + StringUtil.toHex(bytes[j] < 0 ? bytes[j] + 256 : bytes[j], 2); 614 } 615 } catch (UnsupportedEncodingException e) { 616 throw new RuntimeException(e); 617 } 618 stringBuilder.append(encoded); 619 } 620 621 return stringBuilder.toString(); 622 } 623 624 /** 625 * This method will remove all HTML tags. 626 * @see #decodeUrlFormData(String) 627 * @see #decodeUrlPath(String) 628 * @see #decodeUrlToDisplayString(String) 629 * @see #encodeUrlFormData(String) 630 * @see #encodeUrlPath(String) 631 * @see #encodeUrlMyVariant(String) 632 * @see arcommon.xml.XmlUtil#encodeXmlString(String) 633 * @see arcommon.xml.XmlUtil#decodeXmlString(String) 634 */ 635 // Code copied form https://stackoverflow.com/questions/994331/java-how-to-unescape-html-character-entities-in-java 636 // and modified 637 public static String decodeHtml(String string) { 638 try { 639 HTMLDocument document = new HTMLDocument(); 640 HTMLEditorKit htmlEditorKit = new HTMLEditorKit(); 641 StringReader stringReader = new StringReader("<html><body>" + string); 642 htmlEditorKit.read(stringReader, document, 0); 643 return document.getText(1, document.getLength()); 644 } catch (Exception e) { 645 throw new RuntimeException(e); 646 } 647 } 648 649 public static String downloadContentOf(String urlString) { 650/* String result = downloadContentOf(urlString, true); 651 return result; 652 } 653 654 public static String downloadContentOf(String urlString, boolean throwOnConnectionRefused) {*/ 655 String result = null; 656 try { 657 URL url = new URL(urlString); 658 HttpURLConnection connection = (HttpURLConnection)url.openConnection(); 659 connection.connect(); 660 BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream())); 661 StringBuilder stringBuilder = new StringBuilder(); 662 // Code copied from FileUtil.readFile() 663 // and modified 664 ProgressState progressState = ProgressThreadData.createProgressState(); 665 if (progressState != null) { 666 progressState.setName("Downloading content of " + urlString); 667 int contentLength = connection.getContentLength(); 668 progressState.setMaximum(contentLength); 669 progressState.setUseUnits(true); 670 } 671 672 char[] buffer = new char[100000]; 673 while (true) { // The bufferedReader.ready() method can't be used here, as it will return false even if there is more data to read 674 int count = bufferedReader.read(buffer); 675 if (count <= 0) { 676 break; 677 } 678 if (progressState != null) { 679 progressState.setCurrent(progressState.getCurrent() + count); 680 } 681 stringBuilder.append(new String(buffer, 0, count)); 682 } 683 684 result = stringBuilder.toString(); 685 ProgressThreadData.disposeProgressState(progressState); 686 bufferedReader.close(); 687 connection.disconnect(); 688 } catch (MalformedURLException e) { 689 throw new RuntimeException(e); 690 } catch (IOException e) { 691 throw new RuntimeException(e); 692 } 693 return result; 694 } 695 696 public static void downloadFile(String urlString, String fileName) { 697 try { 698 URL url = new URL(urlString); 699 HttpURLConnection connection = (HttpURLConnection)url.openConnection(); 700 connection.connect(); 701 702 ProgressState progressState = ProgressThreadData.createProgressState(); 703 if (progressState != null) { 704 progressState.setName("Downloading..."); 705 try { 706 int contentLength = connection.getContentLength(); 707 progressState.setMaximum(contentLength); 708 progressState.setUseUnits(true); 709 } catch (NullPointerException e) { 710 ; 711 } 712 } 713 714 byte[] buffer = new byte[100000]; 715 int size; 716 DataInputStream dataInputStream = new DataInputStream(connection.getInputStream()); 717 FileOutputStream fileOutputStream = new FileOutputStream(fileName, false); 718 while ((size = dataInputStream.read(buffer, 0, buffer.length)) > 0) { 719 fileOutputStream.write(buffer, 0, size); 720 if (progressState != null) { 721 progressState.setCurrent(progressState.getCurrent() + size); 722 } 723 } 724 dataInputStream.close(); 725 fileOutputStream.flush(); 726 fileOutputStream.close(); 727 connection.disconnect(); 728 } catch (MalformedURLException e) { 729 throw new RuntimeException(e); 730 } catch (IOException e) { 731 throw new RuntimeException(e); 732 } 733 } 734}