source: josm/trunk/src/org/openstreetmap/josm/io/OverpassDownloadReader.java@ 9352

Last change on this file since 9352 was 9318, checked in by simon04, 8 years ago

fix #11693 - Overpass download: set default timeout to 180s

File size: 6.0 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.io;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.io.InputStream;
7import java.util.regex.Matcher;
8import java.util.regex.Pattern;
9
10import javax.xml.stream.XMLStreamConstants;
11import javax.xml.stream.XMLStreamException;
12
13import org.openstreetmap.josm.data.Bounds;
14import org.openstreetmap.josm.data.DataSource;
15import org.openstreetmap.josm.data.osm.DataSet;
16import org.openstreetmap.josm.gui.progress.ProgressMonitor;
17import org.openstreetmap.josm.tools.HttpClient;
18import org.openstreetmap.josm.tools.Utils;
19
20/**
21 * Read content from an Overpass server.
22 *
23 * @since 8744
24 */
25public class OverpassDownloadReader extends BoundingBoxDownloader {
26
27 final String overpassServer;
28 final String overpassQuery;
29
30 /**
31 * Constructs a new {@code OverpassDownloadReader}.
32 *
33 * @param downloadArea The area to download
34 * @param overpassServer The Overpass server to use
35 * @param overpassQuery The Overpass query
36 */
37 public OverpassDownloadReader(Bounds downloadArea, String overpassServer, String overpassQuery) {
38 super(downloadArea);
39 this.overpassServer = overpassServer;
40 this.overpassQuery = overpassQuery.trim();
41 }
42
43 @Override
44 protected String getBaseUrl() {
45 return overpassServer;
46 }
47
48 @Override
49 protected String getRequestForBbox(double lon1, double lat1, double lon2, double lat2) {
50 if (overpassQuery.isEmpty())
51 return super.getRequestForBbox(lon1, lat1, lon2, lat2);
52 else {
53 String realQuery = completeOverpassQuery(overpassQuery);
54 return "interpreter?data=" + Utils.encodeUrl(realQuery)
55 + "&bbox=" + lon1 + ',' + lat1 + ',' + lon2 + ',' + lat2;
56 }
57 }
58
59 private static String completeOverpassQuery(String query) {
60 int firstColon = query.indexOf(';');
61 if (firstColon == -1) {
62 return "[bbox];" + query;
63 }
64 int bboxPos = query.indexOf("[bbox");
65 if (bboxPos > -1 && bboxPos < firstColon) {
66 return query;
67 }
68
69 int bracketCount = 0;
70 int pos = 0;
71 for (; pos < firstColon; ++pos) {
72 if (query.charAt(pos) == '[')
73 ++bracketCount;
74 else if (query.charAt(pos) == ']')
75 --bracketCount;
76 else if (bracketCount == 0) {
77 if (!Character.isWhitespace(query.charAt(pos)))
78 break;
79 }
80 }
81
82 if (pos < firstColon) {
83 // We start with a statement, not with declarations
84 return "[bbox];" + query;
85 }
86
87 // We start with declarations. Add just one more declaration in this case.
88 return "[bbox]" + query;
89 }
90
91 @Override
92 protected InputStream getInputStreamRaw(String urlStr, ProgressMonitor progressMonitor, String reason,
93 boolean uncompressAccordingToContentDisposition) throws OsmTransferException {
94 try {
95 return super.getInputStreamRaw(urlStr, progressMonitor, reason, uncompressAccordingToContentDisposition);
96 } catch (OsmApiException ex) {
97 final String errorIndicator = "Error</strong>: ";
98 if (ex.getMessage() != null && ex.getMessage().contains(errorIndicator)) {
99 final String errorPlusRest = ex.getMessage().split(errorIndicator)[1];
100 if (errorPlusRest != null) {
101 final String error = errorPlusRest.split("</")[0];
102 ex.setErrorHeader(error);
103 }
104 }
105 throw ex;
106 }
107 }
108
109 @Override
110 protected void adaptRequest(HttpClient request) {
111 // see https://wiki.openstreetmap.org/wiki/Overpass_API/Overpass_QL#timeout
112 final Matcher timeoutMatcher = Pattern.compile("\\[timeout:(\\d+)\\]").matcher(overpassQuery);
113 final int timeout;
114 if (timeoutMatcher.find()) {
115 timeout = 1000 * Integer.parseInt(timeoutMatcher.group(1));
116 } else {
117 timeout = 180_000;
118 }
119 request.setConnectTimeout(timeout);
120 request.setReadTimeout(timeout);
121 }
122
123 @Override
124 protected String getTaskName() {
125 return tr("Contacting Server...");
126 }
127
128 @Override
129 protected DataSet parseDataSet(InputStream source, ProgressMonitor progressMonitor) throws IllegalDataException {
130 return new OsmReader() {
131 @Override
132 protected void parseUnknown(boolean printWarning) throws XMLStreamException {
133 if ("remark".equals(parser.getLocalName())) {
134 if (parser.getEventType() == XMLStreamConstants.START_ELEMENT) {
135 final String text = parser.getElementText();
136 if (text.contains("runtime error")) {
137 throw new XMLStreamException(text);
138 }
139 }
140 }
141 super.parseUnknown(printWarning);
142 }
143 }.doParseDataSet(source, progressMonitor);
144 }
145
146 @Override
147 public DataSet parseOsm(ProgressMonitor progressMonitor) throws OsmTransferException {
148
149 DataSet ds = super.parseOsm(progressMonitor);
150
151 // add bounds if necessary (note that Overpass API does not return bounds in the response XML)
152 if (ds != null && ds.dataSources.isEmpty()) {
153 if (crosses180th) {
154 Bounds bounds = new Bounds(lat1, lon1, lat2, 180.0);
155 DataSource src = new DataSource(bounds, getBaseUrl());
156 ds.dataSources.add(src);
157
158 bounds = new Bounds(lat1, -180.0, lat2, lon2);
159 src = new DataSource(bounds, getBaseUrl());
160 ds.dataSources.add(src);
161 } else {
162 Bounds bounds = new Bounds(lat1, lon1, lat2, lon2);
163 DataSource src = new DataSource(bounds, getBaseUrl());
164 ds.dataSources.add(src);
165 }
166 }
167
168 return ds;
169 }
170}
Note: See TracBrowser for help on using the repository browser.