- Timestamp:
- 2015-12-26T23:42:03+01:00 (9 years ago)
- Location:
- trunk/src/org/openstreetmap/josm
- Files:
-
- 1 added
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/data/oauth/OAuthParameters.java
r8513 r9172 7 7 import oauth.signpost.OAuthConsumer; 8 8 import oauth.signpost.OAuthProvider; 9 import oauth.signpost.basic.DefaultOAuthConsumer;10 import oauth.signpost.basic.DefaultOAuthProvider;11 9 12 10 import org.openstreetmap.josm.Main; … … 220 218 */ 221 219 public OAuthConsumer buildConsumer() { 222 return new DefaultOAuthConsumer(consumerKey, consumerSecret);220 return new SignpostAdapters.OAuthConsumer(consumerKey, consumerSecret); 223 221 } 224 222 … … 232 230 public OAuthProvider buildProvider(OAuthConsumer consumer) { 233 231 CheckParameterUtil.ensureParameterNotNull(consumer, "consumer"); 234 return new DefaultOAuthProvider(232 return new SignpostAdapters.OAuthProvider( 235 233 requestTokenUrl, 236 234 accessTokenUrl, -
trunk/src/org/openstreetmap/josm/gui/oauth/OsmOAuthAuthorizationClient.java
r8540 r9172 5 5 6 6 import java.io.BufferedReader; 7 import java.io.DataOutputStream;8 7 import java.io.IOException; 9 import java.io.InputStream;10 import java.io.InputStreamReader;11 8 import java.lang.reflect.Field; 12 9 import java.net.HttpURLConnection; … … 25 22 import oauth.signpost.OAuthConsumer; 26 23 import oauth.signpost.OAuthProvider; 27 import oauth.signpost.basic.DefaultOAuthProvider;28 24 import oauth.signpost.exception.OAuthException; 29 25 … … 36 32 import org.openstreetmap.josm.io.OsmTransferCanceledException; 37 33 import org.openstreetmap.josm.tools.CheckParameterUtil; 34 import org.openstreetmap.josm.tools.HttpClient; 38 35 import org.openstreetmap.josm.tools.Utils; 39 36 … … 47 44 private final OAuthProvider provider; 48 45 private boolean canceled; 49 private Http URLConnectionconnection;46 private HttpClient.Response connection; 50 47 51 48 private static class SessionId { … … 99 96 */ 100 97 public void cancel() { 101 DefaultOAuthProvider p = (DefaultOAuthProvider) provider;102 98 canceled = true; 103 if (p != null) {99 if (provider != null) { 104 100 try { 105 Field f = p.getClass().getDeclaredField("connection"); 101 // TODO 102 Field f = provider.getClass().getDeclaredField("connection"); 106 103 f.setAccessible(true); 107 HttpURLConnection con = (HttpURLConnection) f.get(p );104 HttpURLConnection con = (HttpURLConnection) f.get(provider); 108 105 if (con != null) { 109 106 con.disconnect(); … … 195 192 } 196 193 197 protected String extractToken(HttpURLConnection connection) { 198 try ( 199 InputStream is = connection.getInputStream(); 200 BufferedReader r = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8)) 201 ) { 194 protected String extractToken() { 195 try (BufferedReader r = connection.getContentReader()) { 202 196 String c; 203 197 Pattern p = Pattern.compile(".*authenticity_token.*value=\"([^\"]+)\".*"); … … 215 209 } 216 210 217 protected SessionId extractOsmSession( HttpURLConnection connection) {218 List<String> setCookies = connection.getHeaderFields( ).get("Set-Cookie");211 protected SessionId extractOsmSession() { 212 List<String> setCookies = connection.getHeaderFields("Set-Cookie"); 219 213 if (setCookies == null) 220 214 // no cookies set … … 234 228 if ("_osm_session".equals(kv[0])) { 235 229 // osm session cookie found 236 String token = extractToken( connection);230 String token = extractToken(); 237 231 if (token == null) 238 232 return null; … … 309 303 URL url = new URL(sb.toString()); 310 304 synchronized (this) { 311 connection = Utils.openHttpConnection(url); 312 } 313 connection.setRequestMethod("GET"); 314 connection.setDoInput(true); 315 connection.setDoOutput(false); 316 connection.connect(); 317 SessionId sessionId = extractOsmSession(connection); 305 connection = HttpClient.create(url).connect(); 306 } 307 SessionId sessionId = extractOsmSession(); 318 308 if (sessionId == null) 319 309 throw new OsmOAuthAuthorizationException( … … 339 329 URL url = new URL(getAuthoriseUrl(requestToken)); 340 330 synchronized (this) { 341 connection = Utils.openHttpConnection(url); 342 } 343 connection.setRequestMethod("GET"); 344 connection.setDoInput(true); 345 connection.setDoOutput(false); 346 connection.setRequestProperty("Cookie", "_osm_session=" + sessionId.id + "; _osm_username=" + sessionId.userName); 347 connection.connect(); 348 sessionId.token = extractToken(connection); 331 connection = HttpClient.create(url) 332 .setHeader("Cookie", "_osm_session=" + sessionId.id + "; _osm_username=" + sessionId.userName) 333 .connect(); 334 } 335 sessionId.token = extractToken(); 349 336 if (sessionId.token == null) 350 337 throw new OsmOAuthAuthorizationException(tr("OSM website did not return a session cookie in response to ''{0}'',", … … 362 349 try { 363 350 URL url = new URL(buildOsmLoginUrl()); 364 synchronized (this) { 365 connection = Utils.openHttpConnection(url); 366 } 367 connection.setRequestMethod("POST"); 368 connection.setDoInput(true); 369 connection.setDoOutput(true); 370 connection.setUseCaches(false); 351 final HttpClient client = HttpClient.create(url, "POST").useCache(false); 371 352 372 353 Map<String, String> parameters = new HashMap<>(); … … 376 357 parameters.put("commit", "Login"); 377 358 parameters.put("authenticity_token", sessionId.token); 378 379 String request = buildPostRequest(parameters); 380 381 connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); 382 connection.setRequestProperty("Content-Length", Integer.toString(request.length())); 383 connection.setRequestProperty("Cookie", "_osm_session=" + sessionId.id); 359 client.setRequestBody(buildPostRequest(parameters).getBytes(StandardCharsets.UTF_8)); 360 361 client.setHeader("Content-Type", "application/x-www-form-urlencoded"); 362 client.setHeader("Cookie", "_osm_session=" + sessionId.id); 384 363 // make sure we can catch 302 Moved Temporarily below 385 connection.setInstanceFollowRedirects(false); 386 387 connection.connect(); 388 389 try (DataOutputStream dout = new DataOutputStream(connection.getOutputStream())) { 390 dout.writeBytes(request); 391 dout.flush(); 364 client.setMaxRedirects(-1); 365 366 synchronized (this) { 367 connection = client.connect(); 392 368 } 393 369 … … 415 391 URL url = new URL(buildOsmLogoutUrl()); 416 392 synchronized (this) { 417 connection = Utils.openHttpConnection(url); 418 } 419 connection.setRequestMethod("GET"); 420 connection.setDoInput(true); 421 connection.setDoOutput(false); 422 connection.connect(); 393 connection = HttpClient.create(url).connect(); 394 } 423 395 } catch (IOException e) { 424 396 throw new OsmOAuthAuthorizationException(e); … … 461 433 try { 462 434 URL url = new URL(oauthProviderParameters.getAuthoriseUrl()); 463 synchronized (this) { 464 connection = Utils.openHttpConnection(url); 465 } 466 connection.setRequestMethod("POST"); 467 connection.setDoInput(true); 468 connection.setDoOutput(true); 469 connection.setUseCaches(false); 470 connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); 471 connection.setRequestProperty("Content-Length", Integer.toString(request.length())); 472 connection.setRequestProperty("Cookie", "_osm_session=" + sessionId.id + "; _osm_username=" + sessionId.userName); 473 connection.setInstanceFollowRedirects(false); 474 475 connection.connect(); 476 477 try (DataOutputStream dout = new DataOutputStream(connection.getOutputStream())) { 478 dout.writeBytes(request); 479 dout.flush(); 435 final HttpClient client = HttpClient.create(url, "POST").useCache(false); 436 client.setHeader("Content-Type", "application/x-www-form-urlencoded"); 437 client.setHeader("Cookie", "_osm_session=" + sessionId.id + "; _osm_username=" + sessionId.userName); 438 client.setMaxRedirects(-1); 439 client.setRequestBody(request.getBytes(StandardCharsets.UTF_8)); 440 441 synchronized (this) { 442 connection = client.connect(); 480 443 } 481 444 -
trunk/src/org/openstreetmap/josm/gui/oauth/TestAccessTokenTask.java
r9078 r9172 25 25 import org.openstreetmap.josm.io.auth.DefaultAuthenticator; 26 26 import org.openstreetmap.josm.tools.CheckParameterUtil; 27 import org.openstreetmap.josm.tools. Utils;27 import org.openstreetmap.josm.tools.HttpClient; 28 28 import org.openstreetmap.josm.tools.XmlParsingException; 29 29 import org.w3c.dom.Document; … … 46 46 private final Component parent; 47 47 private final String apiUrl; 48 private Http URLConnectionconnection;48 private HttpClient.Response connection; 49 49 50 50 /** … … 80 80 protected void finish() {} 81 81 82 protected void sign(Http URLConnectioncon) throws OAuthException {82 protected void sign(HttpClient con) throws OAuthException { 83 83 OAuthConsumer consumer = oauthParameters.buildConsumer(); 84 84 consumer.setTokenWithSecret(token.getKey(), token.getSecret()); … … 103 103 authenticatorEnabled = DefaultAuthenticator.getInstance().isEnabled(); 104 104 DefaultAuthenticator.getInstance().setEnabled(false); 105 106 final HttpClient client = HttpClient.create(url); 107 sign(client); 105 108 synchronized (this) { 106 connection = Utils.openHttpConnection(url);109 connection = client.connect(); 107 110 } 108 109 connection.setDoOutput(true);110 connection.setRequestMethod("GET");111 sign(connection);112 connection.connect();113 111 114 112 if (connection.getResponseCode() == HttpURLConnection.HTTP_UNAUTHORIZED) … … 122 120 if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) 123 121 throw new OsmApiException(connection.getResponseCode(), connection.getHeaderField("Error"), null); 124 Document d = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(connection.get InputStream());122 Document d = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(connection.getContent()); 125 123 return OsmServerUserInfoReader.buildFromXML(d); 126 124 } catch (SAXException | ParserConfigurationException e) { -
trunk/src/org/openstreetmap/josm/gui/preferences/server/ApiUrlTestTask.java
r8510 r9172 20 20 import org.openstreetmap.josm.io.OsmTransferException; 21 21 import org.openstreetmap.josm.tools.CheckParameterUtil; 22 import org.openstreetmap.josm.tools. Utils;22 import org.openstreetmap.josm.tools.HttpClient; 23 23 import org.xml.sax.InputSource; 24 24 import org.xml.sax.SAXException; … … 36 36 private boolean success; 37 37 private final Component parent; 38 private Http URLConnectionconnection;38 private HttpClient.Response connection; 39 39 40 40 /** … … 177 177 178 178 synchronized (this) { 179 connection = Utils.openHttpConnection(capabilitiesUrl); 180 } 181 connection.setDoInput(true); 182 connection.setDoOutput(false); 183 connection.setRequestMethod("GET"); 184 connection.connect(); 179 connection = HttpClient.create(capabilitiesUrl).connect(); 180 } 185 181 186 182 if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) { … … 190 186 191 187 try { 192 Capabilities.CapabilitiesParser.parse(new InputSource(connection.get InputStream()));188 Capabilities.CapabilitiesParser.parse(new InputSource(connection.getContent())); 193 189 } catch (SAXException | ParserConfigurationException e) { 194 190 Main.warn(e.getMessage()); -
trunk/src/org/openstreetmap/josm/io/OsmApi.java
r9078 r9172 5 5 import static org.openstreetmap.josm.tools.I18n.trn; 6 6 7 import java.io.BufferedReader;8 import java.io.BufferedWriter;9 7 import java.io.IOException; 10 import java.io.InputStream;11 import java.io.InputStreamReader;12 import java.io.OutputStream;13 import java.io.OutputStreamWriter;14 8 import java.io.PrintWriter; 15 9 import java.io.StringReader; … … 42 36 import org.openstreetmap.josm.io.Capabilities.CapabilitiesParser; 43 37 import org.openstreetmap.josm.tools.CheckParameterUtil; 38 import org.openstreetmap.josm.tools.HttpClient; 44 39 import org.openstreetmap.josm.tools.Utils; 45 40 import org.openstreetmap.josm.tools.XmlParsingException; … … 617 612 protected final String sendRequest(String requestMethod, String urlSuffix, String requestBody, ProgressMonitor monitor, 618 613 boolean doAuthenticate, boolean fastFail) throws OsmTransferException { 619 StringBuilder responseBody = new StringBuilder();620 614 int retries = fastFail ? 0 : getMaxRetries(); 621 615 … … 623 617 try { 624 618 url = new URL(new URL(getBaseUrl()), urlSuffix); 625 Main.info(requestMethod + ' ' + url + "... "); 626 Main.debug(requestBody); 627 // fix #5369, see http://www.tikalk.com/java/forums/httpurlconnection-disable-keep-alive 628 activeConnection = Utils.openHttpConnection(url, false); 629 activeConnection.setConnectTimeout(fastFail ? 1000 : Main.pref.getInteger("socket.timeout.connect", 15)*1000); 619 final HttpClient client = HttpClient.create(url, requestMethod).keepAlive(false); 630 620 if (fastFail) { 631 activeConnection.setReadTimeout(1000);621 client.setReadTimeout(1000); 632 622 } 633 activeConnection.setRequestMethod(requestMethod);634 623 if (doAuthenticate) { 635 addAuth( activeConnection);624 addAuth(client); 636 625 } 637 626 638 627 if ("PUT".equals(requestMethod) || "POST".equals(requestMethod) || "DELETE".equals(requestMethod)) { 639 activeConnection.setDoOutput(true); 640 activeConnection.setRequestProperty("Content-type", "text/xml"); 641 try (OutputStream out = activeConnection.getOutputStream()) { 642 // It seems that certain bits of the Ruby API are very unhappy upon 643 // receipt of a PUT/POST message without a Content-length header, 644 // even if the request has no payload. 645 // Since Java will not generate a Content-length header unless 646 // we use the output stream, we create an output stream for PUT/POST 647 // even if there is no payload. 648 if (requestBody != null) { 649 try (BufferedWriter bwr = new BufferedWriter(new OutputStreamWriter(out, StandardCharsets.UTF_8))) { 650 bwr.write(requestBody); 651 bwr.flush(); 652 } 653 } 654 } 628 // It seems that certain bits of the Ruby API are very unhappy upon 629 // receipt of a PUT/POST message without a Content-length header, 630 // even if the request has no payload. 631 // Since Java will not generate a Content-length header unless 632 // we use the output stream, we create an output stream for PUT/POST 633 // even if there is no payload. 634 client.setRequestBody(requestBody.getBytes(StandardCharsets.UTF_8)); 655 635 } 656 636 657 activeConnection .connect();637 activeConnection = client.connect(); 658 638 Main.info(activeConnection.getResponseMessage()); 659 639 int retCode = activeConnection.getResponseCode(); … … 667 647 } 668 648 669 // populate return fields. 670 responseBody.setLength(0); 671 672 // If the API returned an error code like 403 forbidden, getInputStream will fail with an IOException. 673 InputStream i = getConnectionStream(); 674 if (i != null) { 675 // the input stream can be null if both the input and the error stream 676 // are null. Seems to be the case if the OSM server replies a 401 Unauthorized, see #3887. 677 String s; 678 try (BufferedReader in = new BufferedReader(new InputStreamReader(i, StandardCharsets.UTF_8))) { 679 while ((s = in.readLine()) != null) { 680 responseBody.append(s); 681 responseBody.append('\n'); 682 } 683 } 684 } 649 final String responseBody = activeConnection.fetchContent(); 650 685 651 String errorHeader = null; 686 652 // Look for a detailed error message from the server … … 693 659 activeConnection.disconnect(); 694 660 695 if (Main.isDebugEnabled()) {696 Main.debug("RESPONSE: "+ activeConnection.getHeaderFields());697 }698 699 661 errorHeader = errorHeader == null ? null : errorHeader.trim(); 700 String errorBody = responseBody.length() == 0 ? null : responseBody.t oString().trim();662 String errorBody = responseBody.length() == 0 ? null : responseBody.trim(); 701 663 switch(retCode) { 702 664 case HttpURLConnection.HTTP_OK: 703 return responseBody .toString();665 return responseBody; 704 666 case HttpURLConnection.HTTP_GONE: 705 667 throw new OsmApiPrimitiveGoneException(errorHeader, errorBody); … … 729 691 } 730 692 731 private InputStream getConnectionStream() {732 try {733 return activeConnection.getInputStream();734 } catch (IOException ioe) {735 Main.warn(ioe);736 return activeConnection.getErrorStream();737 }738 }739 740 693 /** 741 694 * Replies the API capabilities. -
trunk/src/org/openstreetmap/josm/io/OsmConnection.java
r8846 r9172 5 5 6 6 import java.net.Authenticator.RequestorType; 7 import java.net.HttpURLConnection;8 7 import java.nio.ByteBuffer; 9 8 import java.nio.CharBuffer; … … 19 18 import org.openstreetmap.josm.io.auth.CredentialsManager; 20 19 import org.openstreetmap.josm.tools.Base64; 20 import org.openstreetmap.josm.tools.HttpClient; 21 21 22 22 import oauth.signpost.OAuthConsumer; … … 31 31 public class OsmConnection { 32 32 protected boolean cancel; 33 protected Http URLConnectionactiveConnection;33 protected HttpClient.Response activeConnection; 34 34 protected OAuthParameters oauthParameters; 35 36 /**37 * Initialize the http defaults and the authenticator.38 */39 static {40 try {41 HttpURLConnection.setFollowRedirects(true);42 } catch (SecurityException e) {43 Main.error(e);44 }45 }46 35 47 36 /** … … 50 39 public void cancel() { 51 40 cancel = true; 52 synchronized (this) {53 if (activeConnection != null) {54 activeConnection.setConnectTimeout(100);55 activeConnection.setReadTimeout(100);56 }57 }58 try {59 Thread.sleep(100);60 } catch (InterruptedException ex) {61 Main.warn("InterruptedException in "+getClass().getSimpleName()+" during cancel");62 }63 64 41 synchronized (this) { 65 42 if (activeConnection != null) { … … 75 52 * @throws OsmTransferException if something went wrong. Check for nested exceptions 76 53 */ 77 protected void addBasicAuthorizationHeader(Http URLConnectioncon) throws OsmTransferException {54 protected void addBasicAuthorizationHeader(HttpClient con) throws OsmTransferException { 78 55 CharsetEncoder encoder = StandardCharsets.UTF_8.newEncoder(); 79 56 CredentialsAgentResponse response; … … 98 75 try { 99 76 ByteBuffer bytes = encoder.encode(CharBuffer.wrap(token)); 100 con. addRequestProperty("Authorization", "Basic "+Base64.encode(bytes));77 con.setHeader("Authorization", "Basic "+Base64.encode(bytes)); 101 78 } catch (CharacterCodingException e) { 102 79 throw new OsmTransferException(e); … … 113 90 * @throws OsmTransferException if signing fails 114 91 */ 115 protected void addOAuthAuthorizationHeader(Http URLConnectionconnection) throws OsmTransferException {92 protected void addOAuthAuthorizationHeader(HttpClient connection) throws OsmTransferException { 116 93 if (oauthParameters == null) { 117 94 oauthParameters = OAuthParameters.createFromPreferences(Main.pref); … … 129 106 } 130 107 131 protected void addAuth(Http URLConnectionconnection) throws OsmTransferException {108 protected void addAuth(HttpClient connection) throws OsmTransferException { 132 109 String authMethod = Main.pref.get("osm-server.auth-method", "basic"); 133 110 if ("basic".equals(authMethod)) { -
trunk/src/org/openstreetmap/josm/io/OsmServerReader.java
r9078 r9172 4 4 import static org.openstreetmap.josm.tools.I18n.tr; 5 5 6 import java.io.BufferedReader;7 import java.io.IOException;8 6 import java.io.InputStream; 9 import java.io.InputStreamReader;10 7 import java.net.HttpURLConnection; 11 8 import java.net.MalformedURLException; 12 9 import java.net.URL; 13 import java.nio.charset.StandardCharsets;14 10 import java.util.List; 15 import java.util.Map;16 import java.util.zip.GZIPInputStream;17 import java.util.zip.Inflater;18 import java.util.zip.InflaterInputStream;19 11 20 12 import org.openstreetmap.josm.Main; … … 23 15 import org.openstreetmap.josm.data.osm.DataSet; 24 16 import org.openstreetmap.josm.gui.progress.ProgressMonitor; 25 import org.openstreetmap.josm.tools. Utils;17 import org.openstreetmap.josm.tools.HttpClient; 26 18 27 19 /** … … 129 121 throw new OsmTransferException(e); 130 122 } 131 try { 132 // fix #7640, see http://www.tikalk.com/java/forums/httpurlconnection-disable-keep-alive 133 activeConnection = Utils.openHttpConnection(url, false); 134 } catch (Exception e) { 135 throw new OsmTransferException(tr("Failed to open connection to API {0}.", url.toExternalForm()), e); 136 } 137 Utils.setupURLConnection(activeConnection); 138 if (cancel) { 139 activeConnection.disconnect(); 140 return null; 141 } 142 123 124 final HttpClient client = HttpClient.create(url); 125 client.setReasonForRequest(reason); 143 126 if (doAuthenticate) { 144 addAuth( activeConnection);127 addAuth(client); 145 128 } 146 129 if (cancel) 147 130 throw new OsmTransferCanceledException("Operation canceled"); 148 if (Main.pref.getBoolean("osm-server.use-compression", true)) {149 activeConnection.setRequestProperty("Accept-Encoding", "gzip, deflate");150 }151 131 152 132 try { 153 if (reason != null && !reason.isEmpty()) { 154 Main.info("GET " + url + " (" + reason + ')'); 155 } else { 156 Main.info("GET " + url); 157 } 158 activeConnection.connect(); 133 activeConnection = client.connect(); 159 134 } catch (Exception e) { 160 135 Main.error(e); … … 165 140 } 166 141 try { 167 if (Main.isDebugEnabled()) {168 Main.debug("RESPONSE: "+activeConnection.getHeaderFields());169 }170 142 if (activeConnection.getResponseCode() == HttpURLConnection.HTTP_UNAUTHORIZED) 171 143 throw new OsmApiException(HttpURLConnection.HTTP_UNAUTHORIZED, null, null); … … 174 146 throw new OsmTransferCanceledException("Proxy Authentication Required"); 175 147 176 String encoding = activeConnection.getContentEncoding();177 148 if (activeConnection.getResponseCode() != HttpURLConnection.HTTP_OK) { 178 149 String errorHeader = activeConnection.getHeaderField("Error"); 179 StringBuilder errorBody = new StringBuilder(); 180 try { 181 InputStream i = fixEncoding(activeConnection.getErrorStream(), encoding); 182 if (i != null) { 183 BufferedReader in = new BufferedReader(new InputStreamReader(i, StandardCharsets.UTF_8)); 184 String s; 185 while ((s = in.readLine()) != null) { 186 errorBody.append(s); 187 errorBody.append('\n'); 188 } 189 } 190 } catch (Exception e) { 191 errorBody.append(tr("Reading error text failed.")); 192 } 193 194 throw new OsmApiException(activeConnection.getResponseCode(), errorHeader, errorBody.toString(), url.toString()); 150 final String errorBody = activeConnection.fetchContent(); 151 throw new OsmApiException(activeConnection.getResponseCode(), errorHeader, errorBody, url.toString()); 195 152 } 196 153 197 154 InputStream in = new ProgressInputStream(activeConnection, progressMonitor); 198 155 if (uncompressAccordingToContentDisposition) { 199 in = uncompressAccordingToContentDisposition(in, activeConnection.getHeaderFields());156 activeConnection.uncompressAccordingToContentDisposition(true); 200 157 } 201 return fixEncoding(in, encoding);158 return in; 202 159 } catch (OsmTransferException e) { 203 160 throw e; … … 210 167 } 211 168 212 private static InputStream fixEncoding(InputStream stream, String encoding) throws IOException {213 if ("gzip".equalsIgnoreCase(encoding)) {214 stream = new GZIPInputStream(stream);215 } else if ("deflate".equalsIgnoreCase(encoding)) {216 stream = new InflaterInputStream(stream, new Inflater(true));217 }218 return stream;219 }220 221 private InputStream uncompressAccordingToContentDisposition(InputStream stream, Map<String, List<String>> headerFields) throws IOException {222 List<String> field = headerFields.get("Content-Disposition");223 if (field != null && field.toString().contains(".gz\"")) {224 return Compression.GZIP.getUncompressedInputStream(stream);225 } else if (field != null && field.toString().contains(".bz2\"")) {226 return Compression.BZIP2.getUncompressedInputStream(stream);227 } else {228 return stream;229 }230 }231 232 169 /** 233 170 * Download OSM files from somewhere -
trunk/src/org/openstreetmap/josm/io/ProgressInputStream.java
r8840 r9172 10 10 import org.openstreetmap.josm.gui.progress.NullProgressMonitor; 11 11 import org.openstreetmap.josm.gui.progress.ProgressMonitor; 12 import org.openstreetmap.josm.tools.HttpClient; 12 13 13 14 /** … … 18 19 19 20 private final InputStream in; 21 private final long size; 20 22 private int readSoFar; 21 23 private int lastDialogUpdate; 22 private boolean sizeKnown;23 private final URLConnection connection;24 24 private final ProgressMonitor progressMonitor; 25 25 26 public ProgressInputStream(InputStream in, long size, ProgressMonitor progressMonitor) { 27 if (progressMonitor == null) { 28 progressMonitor = NullProgressMonitor.INSTANCE; 29 } 30 this.in = in; 31 this.size = size; 32 this.progressMonitor = progressMonitor; 33 progressMonitor.beginTask(tr("Contacting OSM Server..."), 1); 34 progressMonitor.indeterminateSubTask(null); 35 initProgressMonitor(); 36 } 37 38 public ProgressInputStream(HttpClient.Response response, ProgressMonitor progressMonitor) throws IOException { 39 this(response.getContent(), response.getContentLength(), progressMonitor); 40 } 41 26 42 public ProgressInputStream(URLConnection con, ProgressMonitor progressMonitor) throws OsmTransferException { 27 this.connection = con;28 43 if (progressMonitor == null) { 29 44 progressMonitor = NullProgressMonitor.INSTANCE; … … 35 50 try { 36 51 this.in = con.getInputStream(); 52 this.size = con.getContentLength(); 37 53 } catch (IOException e) { 38 54 progressMonitor.finishTask(); … … 41 57 throw new OsmTransferException(e); 42 58 } 59 initProgressMonitor(); 60 } 43 61 44 updateSize(); 45 if (!sizeKnown) { 62 protected void initProgressMonitor() { 63 if (size > 0) { 64 progressMonitor.subTask(tr("Downloading OSM data...")); 65 progressMonitor.setTicksCount((int) size); 66 } else { 46 67 progressMonitor.indeterminateSubTask(tr("Downloading OSM data...")); 47 68 } … … 82 103 private void advanceTicker(int amount) { 83 104 readSoFar += amount; 84 updateSize();85 105 86 106 if (readSoFar / 1024 != lastDialogUpdate) { 87 107 lastDialogUpdate++; 88 if (size Known) {108 if (size > 0) { 89 109 progressMonitor.setTicks(readSoFar); 90 110 } … … 92 112 } 93 113 } 94 95 private void updateSize() {96 if (!sizeKnown && connection.getContentLength() > 0) {97 sizeKnown = true;98 progressMonitor.subTask(tr("Downloading OSM data..."));99 progressMonitor.setTicksCount(connection.getContentLength());100 }101 }102 114 } -
trunk/src/org/openstreetmap/josm/tools/HttpClient.java
r9171 r9172 11 11 import java.net.HttpURLConnection; 12 12 import java.net.URL; 13 import java.util.List; 13 14 import java.util.Map; 14 15 import java.util.Scanner; 15 import java.util.concurrent.ConcurrentHashMap; 16 import java.util.TreeMap; 17 import java.util.regex.Matcher; 18 import java.util.regex.Pattern; 16 19 import java.util.zip.GZIPInputStream; 17 20 … … 30 33 private int connectTimeout = Main.pref.getInteger("socket.timeout.connect", 15) * 1000; 31 34 private int readTimeout = Main.pref.getInteger("socket.timeout.read", 30) * 1000; 32 private String accept;33 private String contentType;34 private String acceptEncoding = "gzip";35 private long contentLength;36 35 private byte[] requestBody; 37 36 private long ifModifiedSince; 38 private final Map<String, String> headers = new ConcurrentHashMap<>();37 private final Map<String, String> headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); 39 38 private int maxRedirects = Main.pref.getInteger("socket.maxredirects", 5); 40 39 private boolean useCache; 41 private boolean keepAlive;40 private String reasonForRequest; 42 41 43 42 private HttpClient(URL url, String requestMethod) { 44 43 this.url = url; 45 44 this.requestMethod = requestMethod; 45 this.headers.put("Accept-Encoding", "gzip"); 46 46 } 47 47 48 48 public Response connect() throws IOException { 49 49 final HttpURLConnection connection = (HttpURLConnection) url.openConnection(); 50 connection.setRequestMethod(requestMethod); 50 51 connection.setRequestProperty("User-Agent", Version.getInstance().getFullAgentString()); 51 52 connection.setConnectTimeout(connectTimeout); 52 53 connection.setReadTimeout(readTimeout); 53 if (accept != null) { 54 connection.setRequestProperty("Accept", accept); 55 } 56 if (contentType != null) { 57 connection.setRequestProperty("Content-Type", contentType); 58 } 59 if (acceptEncoding != null) { 60 connection.setRequestProperty("Accept-Encoding", acceptEncoding); 61 } 62 if (contentLength > 0) { 63 connection.setRequestProperty("Content-Length", String.valueOf(contentLength)); 64 } 54 connection.setInstanceFollowRedirects(maxRedirects > 0); 55 if (ifModifiedSince > 0) { 56 connection.setIfModifiedSince(ifModifiedSince); 57 } 58 connection.setUseCaches(useCache); 59 if (!useCache) { 60 connection.setRequestProperty("Cache-Control", "no-cache"); 61 } 62 for (Map.Entry<String, String> header : headers.entrySet()) { 63 if (header.getValue() != null) { 64 connection.setRequestProperty(header.getKey(), header.getValue()); 65 } 66 } 67 65 68 if ("PUT".equals(requestMethod) || "POST".equals(requestMethod) || "DELETE".equals(requestMethod)) { 69 headers.put("Content-Length", String.valueOf(requestBody.length)); 66 70 connection.setDoOutput(true); 67 71 try (OutputStream out = new BufferedOutputStream(connection.getOutputStream())) { 68 72 out.write(requestBody); 69 73 } 70 }71 if (ifModifiedSince > 0) {72 connection.setIfModifiedSince(ifModifiedSince);73 }74 connection.setUseCaches(useCache);75 if (!useCache) {76 connection.setRequestProperty("Cache-Control", "no-cache");77 }78 if (!keepAlive) {79 connection.setRequestProperty("Connection", "close");80 }81 for (Map.Entry<String, String> header : headers.entrySet()) {82 connection.setRequestProperty(header.getKey(), header.getValue());83 74 } 84 75 … … 87 78 try { 88 79 connection.connect(); 89 Main.info("{0} {1} => {2}", requestMethod, url, connection.getResponseCode()); 80 if (reasonForRequest != null && "".equalsIgnoreCase(reasonForRequest)) { 81 Main.info("{0} {1} ({2}) -> {3}", requestMethod, url, reasonForRequest, connection.getResponseCode()); 82 } else { 83 Main.info("{0} {1} -> {2}", requestMethod, url, connection.getResponseCode()); 84 } 85 if (Main.isDebugEnabled()) { 86 Main.debug("RESPONSE: " + connection.getHeaderFields()); 87 } 90 88 } catch (IOException e) { 91 89 //noinspection ThrowableResultOfMethodCallIgnored … … 105 103 Main.info(tr("Download redirected to ''{0}''", redirectLocation)); 106 104 return connect(); 107 } else {105 } else if (maxRedirects == 0) { 108 106 String msg = tr("Too many redirects to the download URL detected. Aborting."); 109 107 throw new IOException(msg); … … 126 124 private final HttpURLConnection connection; 127 125 private final int responseCode; 126 private final String responseMessage; 128 127 private boolean uncompress; 128 private boolean uncompressAccordingToContentDisposition; 129 129 130 130 private Response(HttpURLConnection connection) throws IOException { 131 CheckParameterUtil.ensureParameterNotNull(connection, "connection"); 131 132 this.connection = connection; 132 133 this.responseCode = connection.getResponseCode(); 134 this.responseMessage = connection.getResponseMessage(); 133 135 } 134 136 … … 144 146 } 145 147 148 public Response uncompressAccordingToContentDisposition(boolean uncompressAccordingToContentDisposition) { 149 this.uncompressAccordingToContentDisposition = uncompressAccordingToContentDisposition; 150 return this; 151 } 152 153 /** 154 * @see HttpURLConnection#getURL() 155 */ 156 public URL getURL() { 157 return connection.getURL(); 158 } 159 160 /** 161 * @see HttpURLConnection#getRequestMethod() 162 */ 163 public String getRequestMethod() { 164 return connection.getRequestMethod(); 165 } 166 146 167 /** 147 168 * Returns an input stream that reads from this HTTP connection, or, 148 169 * error stream if the connection failed but the server sent useful data. 170 * 171 * Note: the return value can be null, if both the input and the error stream are null. 172 * Seems to be the case if the OSM server replies a 401 Unauthorized, see #3887 149 173 * 150 174 * @see HttpURLConnection#getInputStream() … … 160 184 in = "gzip".equalsIgnoreCase(getContentEncoding()) ? new GZIPInputStream(in) : in; 161 185 if (uncompress) { 162 return Compression.forContentType(getContentType()).getUncompressedInputStream(in); 163 } else { 164 return in; 165 } 186 final String contentType = getContentType(); 187 Main.debug("Uncompressing input stream according to Content-Type header: {0}", contentType); 188 in = Compression.forContentType(contentType).getUncompressedInputStream(in); 189 } 190 if (uncompressAccordingToContentDisposition) { 191 final String contentDisposition = getHeaderField("Content-Disposition"); 192 final Matcher matcher = Pattern.compile("filename=\"([^\"]+)\"").matcher(contentDisposition); 193 if (matcher.find()) { 194 Main.debug("Uncompressing input stream according to Content-Disposition header: {0}", contentDisposition); 195 in = Compression.byExtension(matcher.group(1)).getUncompressedInputStream(in); 196 } 197 } 198 return in; 166 199 } 167 200 … … 183 216 */ 184 217 public String fetchContent() throws IOException { 185 try (Scanner scanner = new Scanner(getContentReader()) ) {186 return scanner. useDelimiter("\\A").next();218 try (Scanner scanner = new Scanner(getContentReader()).useDelimiter("\\A")) { 219 return scanner.hasNext() ? scanner.next() : ""; 187 220 } 188 221 } … … 198 231 199 232 /** 233 * Gets the response message from this HTTP connection. 234 * 235 * @see HttpURLConnection#getResponseMessage() 236 */ 237 public String getResponseMessage() { 238 return responseMessage; 239 } 240 241 /** 200 242 * Returns the {@code Content-Encoding} header. 201 243 */ … … 219 261 220 262 /** 263 * @see HttpURLConnection#getHeaderField(String) 264 */ 265 public String getHeaderField(String name) { 266 return connection.getHeaderField(name); 267 } 268 269 /** 270 * @see HttpURLConnection#getHeaderFields() 271 */ 272 public List<String> getHeaderFields(String name) { 273 return connection.getHeaderFields().get(name); 274 } 275 276 /** 221 277 * @see HttpURLConnection#disconnect() 222 278 */ 223 279 public void disconnect() { 280 // TODO is this block necessary for disconnecting? 281 // Fix upload aborts - see #263 282 connection.setConnectTimeout(100); 283 connection.setReadTimeout(100); 284 try { 285 Thread.sleep(100); 286 } catch (InterruptedException ex) { 287 Main.warn("InterruptedException in " + getClass().getSimpleName() + " during cancel"); 288 } 289 224 290 connection.disconnect(); 225 291 } … … 239 305 * Creates a new instance for the given URL and a {@code GET} request 240 306 * 241 * @param url 307 * @param url the URL 242 308 * @param requestMethod the HTTP request method to perform when calling 243 309 * @return a new instance … … 245 311 public static HttpClient create(URL url, String requestMethod) { 246 312 return new HttpClient(url, requestMethod); 313 } 314 315 /** 316 * Returns the URL set for this connection. 317 * @see #create(URL) 318 * @see #create(URL, String) 319 */ 320 public URL getURL() { 321 return url; 322 } 323 324 /** 325 * Returns the request method set for this connection. 326 * @see #create(URL, String) 327 */ 328 public String getRequestMethod() { 329 return requestMethod; 330 } 331 332 /** 333 * Returns the set value for the given {@code header}. 334 */ 335 public String getRequestHeader(String header) { 336 return headers.get(header); 247 337 } 248 338 … … 268 358 */ 269 359 public HttpClient keepAlive(boolean keepAlive) { 270 this.keepAlive = keepAlive; 271 return this; 360 return setHeader("Connection", keepAlive ? null : "close"); 272 361 } 273 362 … … 297 386 */ 298 387 public HttpClient setAccept(String accept) { 299 this.accept = accept; 300 return this; 301 } 302 303 /** 304 * Sets the {@code Content-Type} header. 305 * 306 * @return {@code this} 307 */ 308 public HttpClient setContentType(String contentType) { 309 this.contentType = contentType; 310 return this; 311 } 312 313 /** 314 * Sets the {@code Accept-Encoding} header. 315 * 316 * @return {@code this} 317 */ 318 public HttpClient setAcceptEncoding(String acceptEncoding) { 319 this.acceptEncoding = acceptEncoding; 320 return this; 321 } 322 323 /** 324 * Sets the {@code Content-Length} header for {@code PUT}/{@code POST} requests. 325 * 326 * @return {@code this} 327 */ 328 public HttpClient setContentLength(long contentLength) { 329 this.contentLength = contentLength; 330 return this; 388 return setHeader("Accept", accept); 331 389 } 332 390 … … 354 412 * Sets the maximum number of redirections to follow. 355 413 * 414 * Set {@code maxRedirects} to {@code -1} in order to ignore redirects, i.e., 415 * to not throw an {@link IOException} in {@link #connect()}. 416 * 356 417 * @return {@code this} 357 418 */ … … 378 439 public HttpClient setHeaders(Map<String, String> headers) { 379 440 this.headers.putAll(headers); 441 return this; 442 } 443 444 /** 445 * Sets a reason to show on console. Can be {@code null} if no reason is given. 446 */ 447 public HttpClient setReasonForRequest(String reasonForRequest) { 448 this.reasonForRequest = reasonForRequest; 380 449 return this; 381 450 }
Note:
See TracChangeset
for help on using the changeset viewer.