Bump java lib versions in preparation for 1.9.2
[fw/altos] / map-server / altos-mapd / AltosMapd.java
1 /*
2  * Copyright © 2018 Keith Packard <keithp@keithp.com>
3  *
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, either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  */
14
15 package altosmapd;
16
17 import java.net.*;
18 import java.io.*;
19 import java.text.*;
20 import java.util.*;
21 import java.util.concurrent.*;
22
23 import org.altusmetrum.altoslib_14.*;
24
25 public class AltosMapd implements AltosLaunchSiteListener {
26
27         public static int port = 16717;
28
29         public final static int maptype = AltosMap.maptype_hybrid;
30
31         public final static int px_size = 512;
32
33         public final static int scale = 1;
34
35         public static int max_zoom = 17;
36
37         public static double valid_radius = 17000;      /* 17km */
38
39         public String map_dir = null;
40         public String launch_sites_file = null;
41         public String key_file = null;
42
43         public void usage() {
44                 System.out.printf("usage: altos-mapd [--mapdir <map-directory] [--launch-sites <launch-sites-file>]\n" +
45                                   "                  [--radius <valid-radius-m> [--port <port>] [--key <key-file>]\n" +
46                                   "                  [--max-zoom <max-zoom-level>\n");
47                 System.exit(1);
48         }
49
50         private static Semaphore launch_sites_ready;
51
52         private static List<AltosLaunchSite> launch_sites;
53
54         public void notify_launch_sites(List<AltosLaunchSite> sites) {
55                 synchronized (launch_sites_ready) {
56                         if (sites != null) {
57                                 launch_sites = sites;
58                                 launch_sites_ready.release();
59                         }
60                 }
61         }
62
63         private static boolean west_of(double a, double b) {
64                 double  diff = b - a;
65
66                 while (diff >= 360.0)
67                         diff -= 360.0;
68                 while (diff <= -360.0)
69                         diff += 360.0;
70
71                 return diff >= 0;
72         }
73
74         public static boolean check_lat_lon(double lat, double lon, int zoom) {
75
76                 if (zoom > max_zoom)
77                         return false;
78
79                 AltosMapTransform       transform = new AltosMapTransform(px_size, px_size, zoom, new AltosLatLon(lat, lon));
80
81                 AltosLatLon             upper_left = transform.screen_lat_lon(new AltosPointInt(0, 0));
82                 AltosLatLon             lower_right = transform.screen_lat_lon(new AltosPointInt(px_size, px_size));
83
84                 synchronized (launch_sites_ready) {
85                         if (launch_sites == null) {
86                                 try {
87                                         launch_sites_ready.acquire();
88                                 } catch (InterruptedException ie) {
89                                         return false;
90                                 }
91                         }
92                 }
93                 if (launch_sites == null) {
94                         System.out.printf("No launch site data available, refusing all requests\n");
95                         return false;
96                 }
97
98                 for (AltosLaunchSite site : launch_sites) {
99
100                         /* Figure out which point in the tile to
101                          * measure to the site That's one of the edges
102                          * or the site location depend on where the
103                          * site is in relation to the tile
104                          */
105
106                         double          check_lon;
107
108                         if (west_of(site.longitude, upper_left.lon))
109                                 check_lon = upper_left.lon;
110                         else if (west_of(lower_right.lon, site.longitude))
111                                 check_lon = lower_right.lon;
112                         else
113                                 check_lon = site.longitude;
114
115                         double          check_lat;
116
117                         if (site.latitude < lower_right.lat)
118                                 check_lat = lower_right.lat;
119                         else if (upper_left.lat < site.latitude)
120                                 check_lat = upper_left.lat;
121                         else
122                                 check_lat = site.latitude;
123
124                         AltosGreatCircle gc = new AltosGreatCircle(site.latitude, site.longitude,
125                                                                    check_lat, check_lon);
126
127                         if (gc.distance <= valid_radius)
128                                 return true;
129                 }
130
131                 return false;
132         }
133
134         AltosMapdServer server;
135
136         public void process(String[] args) {
137
138                 AltosPreferences.init(new AltosMapdPreferences());
139
140                 int skip = 1;
141                 for (int i = 0; i < args.length; i += skip) {
142                         skip = 1;
143                         if (args[i].equals("--mapdir") && i < args.length-1) {
144                                 map_dir = args[i+1];
145                                 skip = 2;
146                         } else if (args[i].equals("--launch-sites") && i < args.length-1) {
147                                 launch_sites_file = args[i+1];
148                                 skip = 2;
149                         } else if (args[i].equals("--radius") && i < args.length-1) {
150                                 try {
151                                         valid_radius = AltosParse.parse_double_locale(args[i+1]);
152                                 } catch (ParseException pe) {
153                                         usage();
154                                 }
155                                 skip = 2;
156                         } else if (args[i].equals("--port") && i < args.length-1) {
157                                 try {
158                                         port = AltosParse.parse_int(args[i+1]);
159                                 } catch (ParseException pe) {
160                                         usage();
161                                 }
162                                 skip = 2;
163                         } else if (args[i].equals("--key") && i < args.length-1) {
164                                 key_file = args[i+1];
165                                 skip = 2;
166                         } else if (args[i].equals("--max-zoom") && i < args.length-1) {
167                                 try {
168                                         max_zoom = AltosParse.parse_int(args[i+1]);
169                                 } catch (ParseException pe) {
170                                         usage();
171                                 }
172                                 skip = 2;
173                         } else {
174                                 usage();
175                         }
176                 }
177
178                 if (map_dir == null)
179                         usage();
180
181                 if (key_file != null) {
182                         try {
183                                 BufferedReader key_reader = new BufferedReader(new FileReader(key_file));
184
185                                 String line = key_reader.readLine();
186                                 if (line == null || line.length() != 39) {
187                                         System.out.printf("%s: invalid contents %d \"%s\"\n",
188                                                           key_file, line.length(), line);
189                                         usage();
190                                 }
191                                 key_reader.close();
192                                 AltosMapStore.google_maps_api_key = line;
193                         } catch (Exception e) {
194                                 System.out.printf("%s: %s\n", key_file, e.toString());
195                                 usage();
196                         }
197                 }
198
199                 AltosPreferences.mapdir = new File(map_dir);
200
201                 if (launch_sites_file != null)
202                         AltosLaunchSites.launch_sites_url = "file://" + launch_sites_file;
203
204                 launch_sites_ready = new Semaphore(0);
205
206                 new AltosLaunchSites(this);
207
208                 try {
209                         server = new AltosMapdServer(port);
210                 } catch (IOException ie) {
211                         System.out.printf("Cannot bind to port %d: %s\n", port, ie.toString());
212                         usage();
213                 }
214
215                 for (;;) {
216                         try {
217                                 Socket client = server.accept();
218                                 if (client == null) {
219                                         System.out.printf("accept failed\n");
220                                         continue;
221                                 }
222                                 new AltosMapdClient(client);
223                         } catch (Exception e) {
224                                 System.out.printf("Exception %s\n", e.toString());
225                         }
226                 }
227         }
228
229         public void AltosMapd() {
230         }
231
232         public static void main(final String[] args) {
233                 new AltosMapd().process(args);
234         }
235 }