2 * Copyright © 2014 Keith Packard <keithp@keithp.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
18 package org.altusmetrum.altosuilib_6;
24 public class AltosUIMapStore {
27 LinkedList<AltosUIMapStoreListener> listeners = new LinkedList<AltosUIMapStoreListener>();
29 static final int success = 0;
30 static final int loading = 1;
31 static final int failed = 2;
32 static final int bad_request = 3;
33 static final int forbidden = 4;
41 public synchronized void add_listener(AltosUIMapStoreListener listener) {
42 if (!listeners.contains(listener))
43 listeners.add(listener);
46 public synchronized void remove_listener(AltosUIMapStoreListener listener) {
47 listeners.remove(listener);
50 private synchronized void notify_listeners(int status) {
52 for (AltosUIMapStoreListener listener : listeners)
53 listener.notify_store(this, status);
56 static Object forbidden_lock = new Object();
57 static long forbidden_time;
58 static boolean forbidden_set;
60 private int fetch_url() {
65 } catch (java.net.MalformedURLException e) {
70 URLConnection uc = null;
72 uc = u.openConnection();
73 String type = uc.getContentType();
74 int contentLength = uc.getContentLength();
75 if (uc instanceof HttpURLConnection) {
76 int response = ((HttpURLConnection) uc).getResponseCode();
78 case HttpURLConnection.HTTP_FORBIDDEN:
79 case HttpURLConnection.HTTP_PAYMENT_REQUIRED:
80 case HttpURLConnection.HTTP_UNAUTHORIZED:
81 synchronized (forbidden_lock) {
82 forbidden_time = System.nanoTime();
88 InputStream in = new BufferedInputStream(uc.getInputStream());
91 data = new byte[contentLength];
92 while (offset < contentLength) {
93 bytesRead = in.read(data, offset, data.length - offset);
100 if (offset != contentLength)
103 } catch (IOException e) {
108 FileOutputStream out = new FileOutputStream(file);
112 } catch (FileNotFoundException e) {
114 } catch (IOException e) {
122 static Object fetch_lock = new Object();
124 static final long forbidden_interval = 60l * 1000l * 1000l * 1000l;
125 static final long google_maps_ratelimit_ms = 1200;
127 class loader implements Runnable {
131 notify_listeners(success);
135 synchronized(forbidden_lock) {
136 if (forbidden_set && (System.nanoTime() - forbidden_time) < forbidden_interval) {
137 notify_listeners(forbidden);
144 if (!AltosUIVersion.has_google_maps_api_key()) {
145 synchronized (fetch_lock) {
146 long startTime = System.nanoTime();
147 new_status = fetch_url();
148 if (new_status == success) {
149 long duration_ms = (System.nanoTime() - startTime) / 1000000;
150 if (duration_ms < google_maps_ratelimit_ms) {
152 Thread.sleep(google_maps_ratelimit_ms - duration_ms);
153 } catch (InterruptedException e) {
154 Thread.currentThread().interrupt();
160 new_status = fetch_url();
162 notify_listeners(new_status);
166 private void load() {
167 loader l = new loader();
168 Thread lt = new Thread(l);
172 private AltosUIMapStore (String url, File file) {
184 public boolean equals(AltosUIMapStore other) {
185 return url.equals(other.url);
188 static HashMap<String,AltosUIMapStore> stores = new HashMap<String,AltosUIMapStore>();
190 public static AltosUIMapStore get(String url, File file) {
191 AltosUIMapStore store;
192 synchronized(stores) {
193 if (stores.containsKey(url)) {
194 store = stores.get(url);
196 store = new AltosUIMapStore(url, file);
197 stores.put(url, store);