source: josm/trunk/src/org/openstreetmap/josm/io/OsmServerReader.java@ 7206

Last change on this file since 7206 was 7082, checked in by Don-vip, 10 years ago

see #8465 - replace Utils.UTF_8 by StandardCharsets.UTF_8, new in Java 7

  • Property svn:eol-style set to native
File size: 14.3 KB
RevLine 
[6380]1// License: GPL. For details, see LICENSE file.
[18]2package org.openstreetmap.josm.io;
3
[916]4import static org.openstreetmap.josm.tools.I18n.tr;
5
[1670]6import java.io.BufferedReader;
[3511]7import java.io.IOException;
[103]8import java.io.InputStream;
[1670]9import java.io.InputStreamReader;
[18]10import java.net.HttpURLConnection;
[1670]11import java.net.MalformedURLException;
[18]12import java.net.URL;
[7082]13import java.nio.charset.StandardCharsets;
[6803]14import java.util.List;
15import java.util.Map;
[1670]16import java.util.zip.GZIPInputStream;
[228]17import java.util.zip.Inflater;
18import java.util.zip.InflaterInputStream;
[18]19
[34]20import org.openstreetmap.josm.Main;
[4521]21import org.openstreetmap.josm.data.gpx.GpxData;
[1146]22import org.openstreetmap.josm.data.osm.DataSet;
[1811]23import org.openstreetmap.josm.gui.progress.ProgressMonitor;
[5587]24import org.openstreetmap.josm.tools.Utils;
[18]25
26/**
[228]27 * This DataReader reads directly from the REST API of the osm server.
[1169]28 *
[228]29 * It supports plain text transfer as well as gzip or deflate encoded transfers;
30 * if compressed transfers are unwanted, set property osm-server.use-compression
31 * to false.
[153]32 *
[18]33 * @author imi
34 */
[1146]35public abstract class OsmServerReader extends OsmConnection {
[1664]36 private OsmApi api = OsmApi.getOsmApi();
[2124]37 private boolean doAuthenticate = false;
[5494]38 protected boolean gpxParsedProperly;
[1664]39
[1169]40 /**
41 * Open a connection to the given url and return a reader on the input stream
42 * from that connection. In case of user cancel, return <code>null</code>.
[5863]43 * Relative URL's are directed to API base URL.
44 * @param urlStr The url to connect to.
45 * @param progressMonitor progress monitoring and abort handler
[6695]46 * @return A reader reading the input stream (servers answer) or <code>null</code>.
[5863]47 * @throws OsmTransferException thrown if data transfer errors occur
[1169]48 */
[1811]49 protected InputStream getInputStream(String urlStr, ProgressMonitor progressMonitor) throws OsmTransferException {
[6695]50 return getInputStream(urlStr, progressMonitor, null);
51 }
52
53 /**
54 * Open a connection to the given url and return a reader on the input stream
55 * from that connection. In case of user cancel, return <code>null</code>.
56 * Relative URL's are directed to API base URL.
57 * @param urlStr The url to connect to.
58 * @param progressMonitor progress monitoring and abort handler
59 * @param reason The reason to show on console. Can be {@code null} if no reason is given
60 * @return A reader reading the input stream (servers answer) or <code>null</code>.
61 * @throws OsmTransferException thrown if data transfer errors occur
62 */
63 protected InputStream getInputStream(String urlStr, ProgressMonitor progressMonitor, String reason) throws OsmTransferException {
[1875]64 try {
[2035]65 api.initialize(progressMonitor);
[6695]66 String url = urlStr.startsWith("http") ? urlStr : (getBaseUrl() + urlStr);
67 return getInputStreamRaw(url, progressMonitor, reason);
[1875]68 } finally {
69 progressMonitor.invalidate();
70 }
[1670]71 }
[1664]72
[5863]73 /**
[6695]74 * Return the base URL for relative URL requests
[5863]75 * @return base url of API
76 */
[5097]77 protected String getBaseUrl() {
78 return api.getBaseUrl();
79 }
80
[5863]81 /**
82 * Open a connection to the given url and return a reader on the input stream
83 * from that connection. In case of user cancel, return <code>null</code>.
84 * @param urlStr The exact url to connect to.
85 * @param progressMonitor progress monitoring and abort handler
86 * @return An reader reading the input stream (servers answer) or <code>null</code>.
87 * @throws OsmTransferException thrown if data transfer errors occur
88 */
[1811]89 protected InputStream getInputStreamRaw(String urlStr, ProgressMonitor progressMonitor) throws OsmTransferException {
[6695]90 return getInputStreamRaw(urlStr, progressMonitor, null);
91 }
[6787]92
[6695]93 /**
94 * Open a connection to the given url and return a reader on the input stream
95 * from that connection. In case of user cancel, return <code>null</code>.
96 * @param urlStr The exact url to connect to.
97 * @param progressMonitor progress monitoring and abort handler
98 * @param reason The reason to show on console. Can be {@code null} if no reason is given
99 * @return An reader reading the input stream (servers answer) or <code>null</code>.
100 * @throws OsmTransferException thrown if data transfer errors occur
101 */
102 protected InputStream getInputStreamRaw(String urlStr, ProgressMonitor progressMonitor, String reason) throws OsmTransferException {
[6803]103 return getInputStreamRaw(urlStr, progressMonitor, reason, false);
104 }
105
106 /**
107 * Open a connection to the given url and return a reader on the input stream
108 * from that connection. In case of user cancel, return <code>null</code>.
109 * @param urlStr The exact url to connect to.
110 * @param progressMonitor progress monitoring and abort handler
111 * @param reason The reason to show on console. Can be {@code null} if no reason is given
112 * @param uncompressAccordingToContentDisposition Whether to inspect the HTTP header {@code Content-Disposition}
113 * for {@code filename} and uncompress a gzip/bzip2 stream.
114 * @return An reader reading the input stream (servers answer) or <code>null</code>.
115 * @throws OsmTransferException thrown if data transfer errors occur
116 */
[7033]117 @SuppressWarnings("resource")
[6803]118 protected InputStream getInputStreamRaw(String urlStr, ProgressMonitor progressMonitor, String reason, boolean uncompressAccordingToContentDisposition) throws OsmTransferException {
[1608]119 try {
[1875]120 URL url = null;
121 try {
[3021]122 url = new URL(urlStr.replace(" ", "%20"));
[1875]123 } catch(MalformedURLException e) {
124 throw new OsmTransferException(e);
125 }
126 try {
[5324]127 // fix #7640, see http://www.tikalk.com/java/forums/httpurlconnection-disable-keep-alive
[5587]128 activeConnection = Utils.openHttpConnection(url, false);
[1875]129 } catch(Exception e) {
[2181]130 throw new OsmTransferException(tr("Failed to open connection to API {0}.", url.toExternalForm()), e);
[1875]131 }
132 if (cancel) {
133 activeConnection.disconnect();
134 return null;
135 }
[228]136
[2641]137 if (doAuthenticate) {
138 addAuth(activeConnection);
[2124]139 }
[2641]140 if (cancel)
[4310]141 throw new OsmTransferCanceledException();
[1875]142 if (Main.pref.getBoolean("osm-server.use-compression", true)) {
143 activeConnection.setRequestProperty("Accept-Encoding", "gzip, deflate");
144 }
[1169]145
[4172]146 activeConnection.setConnectTimeout(Main.pref.getInteger("socket.timeout.connect",15)*1000);
[1353]147
[1875]148 try {
[6695]149 if (reason != null && !reason.isEmpty()) {
150 Main.info("GET " + url + " (" + reason + ")");
151 } else {
152 Main.info("GET " + url);
153 }
[1875]154 activeConnection.connect();
155 } catch (Exception e) {
[6643]156 Main.error(e);
[5575]157 OsmTransferException ote = new OsmTransferException(tr("Could not connect to the OSM server. Please check your internet connection."), e);
158 ote.setUrl(url.toString());
159 throw ote;
[1875]160 }
161 try {
[6852]162 if (Main.isDebugEnabled()) {
163 Main.debug("RESPONSE: "+activeConnection.getHeaderFields());
164 }
[2641]165 if (activeConnection.getResponseCode() == HttpURLConnection.HTTP_UNAUTHORIZED)
[1875]166 throw new OsmApiException(HttpURLConnection.HTTP_UNAUTHORIZED,null,null);
[1353]167
[2641]168 if (activeConnection.getResponseCode() == HttpURLConnection.HTTP_PROXY_AUTH)
[4310]169 throw new OsmTransferCanceledException();
[2641]170
[3511]171 String encoding = activeConnection.getContentEncoding();
[1875]172 if (activeConnection.getResponseCode() != HttpURLConnection.HTTP_OK) {
173 String errorHeader = activeConnection.getHeaderField("Error");
174 StringBuilder errorBody = new StringBuilder();
[6787]175 try {
176 InputStream i = fixEncoding(activeConnection.getErrorStream(), encoding);
[3511]177 if (i != null) {
[7082]178 BufferedReader in = new BufferedReader(new InputStreamReader(i, StandardCharsets.UTF_8));
[3511]179 String s;
180 while((s = in.readLine()) != null) {
181 errorBody.append(s);
182 errorBody.append("\n");
183 }
[1875]184 }
[1670]185 }
[3511]186 catch(Exception e) {
187 errorBody.append(tr("Reading error text failed."));
188 }
[1875]189
[5584]190 throw new OsmApiException(activeConnection.getResponseCode(), errorHeader, errorBody.toString(), url.toString());
[1670]191 }
[1169]192
[6803]193 InputStream in = new ProgressInputStream(activeConnection, progressMonitor);
194 if (uncompressAccordingToContentDisposition) {
195 in = uncompressAccordingToContentDisposition(in, activeConnection.getHeaderFields());
196 }
197 return fixEncoding(in, encoding);
[6246]198 } catch (OsmTransferException e) {
199 throw e;
200 } catch (Exception e) {
201 throw new OsmTransferException(e);
[1670]202 }
[1875]203 } finally {
204 progressMonitor.invalidate();
[1169]205 }
206 }
207
[6787]208 private InputStream fixEncoding(InputStream stream, String encoding) throws IOException {
[6089]209 if ("gzip".equalsIgnoreCase(encoding)) {
[3511]210 stream = new GZIPInputStream(stream);
[6787]211 } else if ("deflate".equalsIgnoreCase(encoding)) {
[3511]212 stream = new InflaterInputStream(stream, new Inflater(true));
213 }
214 return stream;
215 }
216
[6803]217 private InputStream uncompressAccordingToContentDisposition(InputStream stream, Map<String, List<String>> headerFields) throws IOException {
218 if (headerFields.get("Content-Disposition").toString().contains(".gz\"")) {
219 return Compression.GZIP.getUncompressedInputStream(stream);
220 } else if (headerFields.get("Content-Disposition").toString().contains(".bz2\"")) {
221 return Compression.BZIP2.getUncompressedInputStream(stream);
222 } else {
223 return stream;
224 }
225 }
226
[6244]227 /**
228 * Download OSM files from somewhere
229 * @param progressMonitor The progress monitor
230 * @return The corresponding dataset
[6643]231 * @throws OsmTransferException if any error occurs
[6244]232 */
[5317]233 public abstract DataSet parseOsm(final ProgressMonitor progressMonitor) throws OsmTransferException;
[1169]234
[6244]235 /**
236 * Download OSM Change files from somewhere
237 * @param progressMonitor The progress monitor
238 * @return The corresponding dataset
[6643]239 * @throws OsmTransferException if any error occurs
[6244]240 */
[5317]241 public DataSet parseOsmChange(final ProgressMonitor progressMonitor) throws OsmTransferException {
[4530]242 return null;
243 }
[5361]244
[6244]245 /**
246 * Download BZip2-compressed OSM Change files from somewhere
247 * @param progressMonitor The progress monitor
248 * @return The corresponding dataset
[6643]249 * @throws OsmTransferException if any error occurs
[6244]250 */
[5361]251 public DataSet parseOsmChangeBzip2(final ProgressMonitor progressMonitor) throws OsmTransferException {
252 return null;
253 }
254
[6244]255 /**
256 * Download GZip-compressed OSM Change files from somewhere
257 * @param progressMonitor The progress monitor
258 * @return The corresponding dataset
[6643]259 * @throws OsmTransferException if any error occurs
[6244]260 */
[5361]261 public DataSet parseOsmChangeGzip(final ProgressMonitor progressMonitor) throws OsmTransferException {
262 return null;
263 }
264
[6244]265 /**
266 * Retrieve raw gps waypoints from the server API.
267 * @param progressMonitor The progress monitor
268 * @return The corresponding GPX tracks
269 * @throws OsmTransferException if any error occurs
270 */
[5317]271 public GpxData parseRawGps(final ProgressMonitor progressMonitor) throws OsmTransferException {
[4521]272 return null;
273 }
[5317]274
[6244]275 /**
276 * Retrieve BZip2-compressed GPX files from somewhere.
277 * @param progressMonitor The progress monitor
278 * @return The corresponding GPX tracks
279 * @throws OsmTransferException if any error occurs
280 * @since 6244
281 */
282 public GpxData parseRawGpsBzip2(final ProgressMonitor progressMonitor) throws OsmTransferException {
283 return null;
284 }
285
286 /**
287 * Download BZip2-compressed OSM files from somewhere
288 * @param progressMonitor The progress monitor
289 * @return The corresponding dataset
[6643]290 * @throws OsmTransferException if any error occurs
[6244]291 */
[5317]292 public DataSet parseOsmBzip2(final ProgressMonitor progressMonitor) throws OsmTransferException {
293 return null;
294 }
[5361]295
[6244]296 /**
297 * Download GZip-compressed OSM files from somewhere
298 * @param progressMonitor The progress monitor
299 * @return The corresponding dataset
[6643]300 * @throws OsmTransferException if any error occurs
[6244]301 */
[5361]302 public DataSet parseOsmGzip(final ProgressMonitor progressMonitor) throws OsmTransferException {
303 return null;
304 }
305
[2124]306 /**
[6882]307 * Download Zip-compressed OSM files from somewhere
308 * @param progressMonitor The progress monitor
309 * @return The corresponding dataset
310 * @throws OsmTransferException if any error occurs
311 * @since 6882
312 */
313 public DataSet parseOsmZip(final ProgressMonitor progressMonitor) throws OsmTransferException {
314 return null;
315 }
316
317 /**
[2124]318 * Returns true if this reader is adding authentication credentials to the read
319 * request sent to the server.
[2512]320 *
[2124]321 * @return true if this reader is adding authentication credentials to the read
322 * request sent to the server
323 */
324 public boolean isDoAuthenticate() {
325 return doAuthenticate;
326 }
327
328 /**
329 * Sets whether this reader adds authentication credentials to the read
330 * request sent to the server.
[2512]331 *
[2124]332 * @param doAuthenticate true if this reader adds authentication credentials to the read
333 * request sent to the server
334 */
335 public void setDoAuthenticate(boolean doAuthenticate) {
336 this.doAuthenticate = doAuthenticate;
337 }
[6070]338
[5494]339 /**
340 * Determines if the GPX data has been parsed properly.
341 * @return true if the GPX data has been parsed properly, false otherwise
342 * @see GpxReader#parse
343 */
344 public final boolean isGpxParsedProperly() {
345 return gpxParsedProperly;
346 }
[18]347}
Note: See TracBrowser for help on using the repository browser.