001 // License: GPL. Copyright 2007 by Immanuel Scholz and others 002 package org.openstreetmap.josm.io; 003 004 import static org.openstreetmap.josm.tools.I18n.tr; 005 006 import java.io.IOException; 007 import java.io.InputStream; 008 009 import org.openstreetmap.josm.data.Bounds; 010 import org.openstreetmap.josm.data.gpx.GpxData; 011 import org.openstreetmap.josm.data.osm.DataSet; 012 import org.openstreetmap.josm.gui.progress.ProgressMonitor; 013 import org.xml.sax.SAXException; 014 015 public class BoundingBoxDownloader extends OsmServerReader { 016 017 /** 018 * The boundings of the desired map data. 019 */ 020 protected final double lat1; 021 protected final double lon1; 022 protected final double lat2; 023 protected final double lon2; 024 protected final boolean crosses180th; 025 026 public BoundingBoxDownloader(Bounds downloadArea) { 027 this.lat1 = downloadArea.getMin().lat(); 028 this.lon1 = downloadArea.getMin().lon(); 029 this.lat2 = downloadArea.getMax().lat(); 030 this.lon2 = downloadArea.getMax().lon(); 031 this.crosses180th = downloadArea.crosses180thMeridian(); 032 } 033 034 private GpxData downloadRawGps(String url, ProgressMonitor progressMonitor) throws IOException, OsmTransferException, SAXException { 035 boolean done = false; 036 GpxData result = null; 037 for (int i = 0;!done;++i) { 038 progressMonitor.subTask(tr("Downloading points {0} to {1}...", i * 5000, ((i + 1) * 5000))); 039 InputStream in = getInputStream(url+i, progressMonitor.createSubTaskMonitor(1, true)); 040 if (in == null) { 041 break; 042 } 043 progressMonitor.setTicks(0); 044 GpxReader reader = new GpxReader(in); 045 reader.parse(false); 046 GpxData currentGpx = reader.data; 047 if (result == null) { 048 result = currentGpx; 049 } else if (currentGpx.hasTrackPoints()) { 050 result.mergeFrom(currentGpx); 051 } else{ 052 done = true; 053 } 054 in.close(); 055 activeConnection = null; 056 } 057 result.fromServer = true; 058 return result; 059 } 060 061 /** 062 * Retrieve raw gps waypoints from the server API. 063 * @return A list of all primitives retrieved. Currently, the list of lists 064 * contain only one list, since the server cannot distinguish between 065 * ways. 066 */ 067 @Override 068 public GpxData parseRawGps(ProgressMonitor progressMonitor) throws OsmTransferException { 069 progressMonitor.beginTask("", 1); 070 try { 071 progressMonitor.indeterminateSubTask(tr("Contacting OSM Server...")); 072 if (crosses180th) { 073 // API 0.6 does not support requests crossing the 180th meridian, so make two requests 074 GpxData result = downloadRawGps("trackpoints?bbox="+lon1+","+lat1+",180.0,"+lat2+"&page=", progressMonitor); 075 result.mergeFrom(downloadRawGps("trackpoints?bbox=-180.0,"+lat1+","+lon2+","+lat2+"&page=", progressMonitor)); 076 return result; 077 } else { 078 // Simple request 079 return downloadRawGps("trackpoints?bbox="+lon1+","+lat1+","+lon2+","+lat2+"&page=", progressMonitor); 080 } 081 } catch (IllegalArgumentException e) { 082 // caused by HttpUrlConnection in case of illegal stuff in the response 083 if (cancel) 084 return null; 085 throw new OsmTransferException("Illegal characters within the HTTP-header response.", e); 086 } catch (IOException e) { 087 if (cancel) 088 return null; 089 throw new OsmTransferException(e); 090 } catch (SAXException e) { 091 throw new OsmTransferException(e); 092 } catch (OsmTransferException e) { 093 throw e; 094 } catch (RuntimeException e) { 095 if (cancel) 096 return null; 097 throw e; 098 } finally { 099 progressMonitor.finishTask(); 100 } 101 } 102 103 protected String getRequestForBbox(double lon1, double lat1, double lon2, double lat2) { 104 return "map?bbox=" + lon1 + "," + lat1 + "," + lon2 + "," + lat2; 105 } 106 107 /** 108 * Read the data from the osm server address. 109 * @return A data set containing all data retrieved from that url 110 */ 111 @Override 112 public DataSet parseOsm(ProgressMonitor progressMonitor) throws OsmTransferException { 113 progressMonitor.beginTask(tr("Contacting OSM Server..."), 10); 114 InputStream in = null; 115 try { 116 DataSet ds = null; 117 progressMonitor.indeterminateSubTask(null); 118 if (crosses180th) { 119 // API 0.6 does not support requests crossing the 180th meridian, so make two requests 120 in = getInputStream(getRequestForBbox(lon1, lat1, 180.0, lat2), progressMonitor.createSubTaskMonitor(9, false)); 121 if (in == null) 122 return null; 123 ds = OsmReader.parseDataSet(in, progressMonitor.createSubTaskMonitor(1, false)); 124 125 in = getInputStream(getRequestForBbox(-180.0, lat1, lon2, lat2), progressMonitor.createSubTaskMonitor(9, false)); 126 if (in == null) 127 return null; 128 DataSet ds2 = OsmReader.parseDataSet(in, progressMonitor.createSubTaskMonitor(1, false)); 129 if (ds2 == null) 130 return null; 131 ds.mergeFrom(ds2); 132 133 } else { 134 // Simple request 135 in = getInputStream(getRequestForBbox(lon1, lat1, lon2, lat2), progressMonitor.createSubTaskMonitor(9, false)); 136 if (in == null) 137 return null; 138 ds = OsmReader.parseDataSet(in, progressMonitor.createSubTaskMonitor(1, false)); 139 } 140 return ds; 141 } catch(OsmTransferException e) { 142 throw e; 143 } catch (Exception e) { 144 throw new OsmTransferException(e); 145 } finally { 146 progressMonitor.finishTask(); 147 if (in != null) { 148 try {in.close();} catch(IOException e) {} 149 } 150 activeConnection = null; 151 } 152 } 153 }