1 package tim.prune.function.srtm;
4 import java.io.FileOutputStream;
5 import java.io.IOException;
6 import java.io.InputStream;
7 import java.net.CookieHandler;
8 import java.net.CookieManager;
9 import java.net.CookiePolicy;
11 import java.net.HttpURLConnection;
12 import java.util.ArrayList;
13 import java.util.Base64;
15 import javax.swing.JOptionPane;
18 import tim.prune.GenericFunction;
19 import tim.prune.GpsPrune;
20 import tim.prune.I18nManager;
21 import tim.prune.config.Config;
22 import tim.prune.data.DoubleRange;
23 import tim.prune.gui.ProgressDialog;
26 * Class to provide a download function for the Space Shuttle's SRTM data files.
27 * HGT files are downloaded into memory via HTTP and stored in the map cache.
29 public class DownloadSrtmFunction extends GenericFunction implements Runnable
31 /** Progress dialog */
32 private ProgressDialog _progress = null;
33 /** Flag to check whether this function is currently running or not */
34 private boolean _running = false;
39 * @param inApp App object
41 public DownloadSrtmFunction(App inApp) {
44 CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ALL));
48 /** @return name key */
49 public String getNameKey() {
50 return "function.downloadsrtm";
59 if (_progress == null) {
60 _progress = new ProgressDialog(_parentFrame, getNameKey());
63 // start new thread for time-consuming part
64 new Thread(this).start();
68 * Run method using separate thread
72 // Compile list of tiles to get
73 ArrayList<SrtmTile> tileList = new ArrayList<SrtmTile>();
75 // First, loop to see which tiles are needed
76 DoubleRange lonRange = _app.getTrackInfo().getTrack().getLonRange();
77 DoubleRange latRange = _app.getTrackInfo().getTrack().getLatRange();
78 final int minLon = (int) Math.floor(lonRange.getMinimum());
79 final int maxLon = (int) Math.floor(lonRange.getMaximum());
80 final int minLat = (int) Math.floor(latRange.getMinimum());
81 final int maxLat = (int) Math.floor(latRange.getMaximum());
83 for (int lon=minLon; lon<= maxLon; lon++)
85 for (int lat=minLat; lat <= maxLat; lat++)
87 SrtmTile tile = new SrtmTile(lat, lon);
88 boolean alreadyGot = false;
89 for (int t = 0; t < tileList.size(); t++)
91 if (tileList.get(t).equals(tile)) {
95 if (!alreadyGot) {tileList.add(tile);}
99 downloadTiles(tileList);
106 * Download the tiles of SRTM data
107 * @param inTileList list of tiles to get
109 private void downloadTiles(ArrayList<SrtmTile> inTileList)
111 // Update progress bar
112 if (_progress != null)
114 // advance by 1 for HTTP connection open, then by 1 for every tenth of the download
115 _progress.setMaximum(inTileList.size() * 11);
116 _progress.setValue(0);
119 String errorMessage = null;
121 // Check the cache is ok
122 final String diskCachePath = Config.getConfigString(Config.KEY_DISK_CACHE);
123 if (diskCachePath != null)
125 File srtmDir = new File(diskCachePath, "srtm");
126 if (!srtmDir.exists() && !srtmDir.mkdir()) {
127 // can't create the srtm directory
128 errorMessage = I18nManager.getText("error.downloadsrtm.nocache");
133 errorMessage = I18nManager.getText("error.downloadsrtm.nocache");
136 // Get urls for each tile
137 URL[] urls = TileFinder.getUrls(inTileList);
138 int numDownloaded = 0;
139 for (int t=0; t<inTileList.size() && !_progress.isCancelled(); t++)
144 FileOutputStream outStream = null;
145 InputStream inStream = null;
149 _progress.setValue(t * 10);
150 // See if we've already got this tile or not
151 File outputFile = getFileToWrite(urls[t]);
152 if (outputFile != null)
155 System.out.println("Download: Need to download: " + urls[t]);
156 HttpURLConnection conn = (HttpURLConnection) urls[t].openConnection();
157 String auth = "Basic " + Base64.getEncoder().encodeToString(urls[t].getUserInfo().getBytes());
158 long fileLength = 0L;
160 while (redirects > 0) {
163 conn.setRequestProperty("User-Agent", "GpsPrune v" + GpsPrune.VERSION_NUMBER);
164 conn.setRequestProperty("Authorization", auth);
165 conn.setInstanceFollowRedirects(false);
166 conn.setUseCaches(false);
168 int status = conn.getResponseCode();
171 inStream = conn.getInputStream();
172 fileLength = conn.getContentLengthLong();
175 else if (status == 302)
177 // redirected to SSO server then back to original resource
178 String newUrl = conn.getHeaderField("Location");
179 conn = (HttpURLConnection) (new URL(newUrl)).openConnection();
183 throw new IOException("Invalid response from server: " +status+conn.getContent());
186 _progress.setValue(t * 10 + 1);
187 outStream = new FileOutputStream(outputFile);
189 // Copy all the bytes to the file
192 while ((c = inStream.read()) != -1)
196 _progress.setValue(t * 10 + 1 + (int) ((10 * written) / fileLength));
201 else System.out.println("Don't need to download: " + urls[t].getFile());
203 catch (IOException ioe) {errorMessage = ioe.getClass().getName() + " - " + ioe.getMessage();
205 // Make sure streams are closed
206 try {inStream.close();} catch (Exception e) {}
207 try {outStream.close();} catch (Exception e) {}
212 if (_progress.isCancelled()) {
216 if (errorMessage != null) {
217 _app.showErrorMessageNoLookup(getNameKey(), errorMessage);
219 else if (numDownloaded == 1)
221 JOptionPane.showMessageDialog(_parentFrame, I18nManager.getTextWithNumber("confirm.downloadsrtm.1", numDownloaded),
222 I18nManager.getText(getNameKey()), JOptionPane.INFORMATION_MESSAGE);
224 else if (numDownloaded > 1)
226 JOptionPane.showMessageDialog(_parentFrame, I18nManager.getTextWithNumber("confirm.downloadsrtm", numDownloaded),
227 I18nManager.getText(getNameKey()), JOptionPane.INFORMATION_MESSAGE);
229 else if (inTileList.size() > 0) {
230 _app.showErrorMessage(getNameKey(), "confirm.downloadsrtm.none");
235 * See whether the SRTM file is already available locally
236 * @param inUrl URL for online resource
237 * @return file object to write to, or null if already there
239 private static File getFileToWrite(URL inUrl)
241 String diskCachePath = Config.getConfigString(Config.KEY_DISK_CACHE);
242 if (diskCachePath != null)
244 File srtmDir = new File(diskCachePath, "srtm");
245 if (srtmDir.exists() && srtmDir.isDirectory() && srtmDir.canRead())
247 File srtmFile = new File(srtmDir, new File(inUrl.getFile()).getName());
248 if (!srtmFile.exists() || !srtmFile.canRead() || srtmFile.length() <= 400) {
257 * @return true if a thread is currently running
259 public boolean isRunning()