-SUBDIRS=ao-tools src doc icon altoslib libaltos altosuilib altosui micropeak ao-utils altosdroid telegps
+SUBDIRS=ao-tools src doc icon altoslib libaltos altosuilib altosui micropeak ao-utils altosdroid telegps map-server
EXTRA_DIST = ChangeLog
center.lat, center.lon, z, px_size/scale, px_size/scale, AltosMap.maptype_names[maptype], format_string);
}
- public int status() {
+ public synchronized int status() {
return status;
}
HAVE_GOOGLE_KEY="no"
fi
+AC_ARG_ENABLE(faketime, AS_HELP_STRING([--enable-faketime],
+ [Use faketime program to ensure pdf files are reproducible (default=no)]),
+ [FAKETIME=$enableval], [FAKETIME=no])
+
+AM_CONDITIONAL(FAKETIME, [test x$FAKETIME = xyes])
+
AC_SUBST(GOOGLEKEY)
AC_PROG_CC
ao-tools/ao-chaosread/Makefile
ao-tools/ao-makebin/Makefile
ao-utils/Makefile
+map-server/Makefile
+map-server/altos-mapd/Makefile
+map-server/altos-map/Makefile
src/Version
])
# http://docbook.sourceforge.net/release/xsl/current/README
#
-FAKETIME=$(RELEASE_DATE) 00:00:00
+if FAKETIME
+FAKETIME=TZ=UTC faketime -f '$(RELEASE_DATE) 00:00:00 i0'
+endif
RELNOTES_INC=\
release-notes-1.8.7.inc \
.raw.html:
a2x -a docinfo -f xhtml --xsltproc-opts "--stringparam toc.section.depth 2" --xsl-file $(HTML_STYLE) --stylesheet=$(STYLESHEET) $*.raw
case $* in release-notes*) ./fix-html $*.html ;; esac
+ $(FAKETIME) a2x -a docinfo -f pdf --xsltproc-opts "--stringparam toc.section.depth 2" --xsl-file $(FOP_STYLE) --fop --fop-opts="-c $(FOP_XCONF)" $*.raw
.html.pdf:
- TZ=UTC faketime -f '$(FAKETIME) i0' a2x -a docinfo -f pdf --xsltproc-opts "--stringparam toc.section.depth 2" --xsl-file $(FOP_STYLE) --fop --fop-opts="-c $(FOP_XCONF)" $*.raw
+ echo $@
.tmpl.xsl:
xsltproc --output $@ /usr/share/xml/docbook/stylesheet/docbook-xsl/template/titlepage.xsl $*.tmpl
--- /dev/null
+SUBDIRS=altos-mapd altos-map
--- /dev/null
+altos-map
+altos-map-jdb
+altos-map-test
+*.jar
+*.stamp
+classes
--- /dev/null
+/*
+ * Copyright © 2018 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+package altosmap;
+
+import java.net.*;
+import java.io.*;
+import java.util.*;
+import java.text.*;
+
+import org.altusmetrum.altoslib_13.*;
+
+public class AltosMap {
+
+ public final static int port = 16717;
+
+ String query_string;
+ String remote_addr;
+
+ public String reason_string(int code) {
+ switch (code) {
+ case 200:
+ return "OK";
+ case 400:
+ return "Bad Request";
+ case 403:
+ return "Forbidden";
+ case 404:
+ return "Not Found";
+ case 408:
+ return "Request Timeout";
+ default:
+ return "Failure";
+ }
+ }
+
+ public void write_status(int status) {
+ System.out.printf("Status: %d %s\n", status, reason_string(status));
+ }
+
+ public void write_type(String type) {
+ System.out.printf("Content-Type: %s\n", type);
+ }
+
+ public void fail(int status, String reason) {
+ write_status(status);
+ write_type("text/html");
+ System.out.printf("\n");
+ System.out.printf("<html>\n");
+ System.out.printf("<head><title>Map Fetch Failure</title></head>\n");
+ System.out.printf("<body>%s</body>\n", reason);
+ System.out.printf("</html>\n");
+ System.exit(1);
+ }
+
+ public void process() {
+ query_string = System.getenv("QUERY_STRING");
+
+ if (query_string == null)
+ fail(400, "Missing query string");
+
+ remote_addr = System.getenv("REMOTE_ADDR");
+
+ if (remote_addr == null)
+ fail(400, "Missing remote address");
+
+ String[] queries = query_string.split("&");
+
+ double lon = AltosLib.MISSING;
+ double lat = AltosLib.MISSING;
+ int zoom = AltosLib.MISSING;
+
+ try {
+ for (String query : queries) {
+ String[] q = query.split("=");
+ if (q.length >= 2) {
+ String name = q[0];
+ String value = q[1];
+ if (name.equals("lon"))
+ lon = AltosParse.parse_double_net(value);
+ else if (name.equals("lat"))
+ lat = AltosParse.parse_double_net(value);
+ else if (name.equals("zoom"))
+ zoom = AltosParse.parse_int(value);
+ else
+ fail(400, String.format("Extra query param \"%s\"", query));
+ }
+ }
+ } catch (ParseException pe) {
+ fail(400, String.format("Invalid query: %s", pe.toString()));
+ }
+
+ if (lon == AltosLib.MISSING)
+ fail(400, "Missing longitude");
+ if (lat == AltosLib.MISSING)
+ fail(400, "Missing latitude");
+ if (zoom == AltosLib.MISSING)
+ fail(400, "Missing zoom");
+
+ try {
+ Socket socket = new Socket(InetAddress.getLoopbackAddress(), port);
+
+ AltosJson request = new AltosJson();
+
+ request.put("lat", lat);
+ request.put("lon", lon);
+ request.put("zoom", zoom);
+ request.put("remote_addr", remote_addr);
+
+ Writer writer = new PrintWriter(socket.getOutputStream());
+ request.write(writer);
+ writer.flush();
+
+ AltosJson reply = AltosJson.fromInputStream(socket.getInputStream());
+
+ int status = reply.get_int("status", 400);
+
+ if (status != 200)
+ fail(status, "Bad cache status");
+
+ String filename = reply.get_string("filename", null);
+ try {
+ File file = new File(filename);
+ long length = file.length();
+ FileInputStream in = new FileInputStream(file);
+ String content_type = reply.get_string("content_type", null);
+ System.out.printf("Content-Type: %s\n", content_type);
+ System.out.printf("Content-Length: %d\n", file.length());
+ System.out.printf("\n");
+ byte[] buf = new byte[4096];
+ int bytes_read;
+ while ((bytes_read = in.read(buf)) > 0)
+ System.out.write(buf);
+ } catch (IOException ie) {
+ fail(404, String.format("IO Exception: %s", ie.toString()));
+ }
+ } catch (Exception e) {
+ fail(404, String.format("Exception %s", e.toString()));
+ }
+ }
+
+ public AltosMap() {
+ }
+
+ public static void main(final String[] args) {
+
+ new AltosMap().process();
+
+ }
+}
--- /dev/null
+JAVAROOT=classes
+AM_JAVACFLAGS=-target 1.6 -encoding UTF-8 -Xlint:deprecation -Xlint:unchecked -source 6
+
+altoslibdir=$(libdir)/altos
+
+CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH="$(JAVAROOT):../../altoslib/*"
+
+bin_SCRIPTS=altos-map
+
+altosmap_JAVA = \
+ AltosMap.java
+
+ALTOSLIB_CLASS=\
+ altoslib_$(ALTOSLIB_VERSION).jar
+
+JAR=altosmap.jar
+
+FATJAR=altosmap-fat.jar
+
+all-local: classes/altosmap $(JAR) altos-map altos-map-test altos-map-jdb
+
+install-altosmapJAVA: altosmap.jar
+ @$(NORMAL_INSTALL)
+ test -z "$(altosmapdir)" || $(MKDIR_P) "$(DESTDIR)$(altosmapdir)"
+ echo " $(INSTALL_DATA)" "$<" "'$(DESTDIR)$(altosmapdir)/altosmap.jar'"; \
+ $(INSTALL_DATA) "$<" "$(DESTDIR)$(altosmapdir)"
+
+classes/altosmap:
+ mkdir -p classes/altosmap
+
+$(JAR): classaltosmap.stamp Manifest.txt $(ALTOSLIB_CLASS)
+ jar cfm $@ Manifest.txt \
+ -C classes altosmap
+
+altosmapdir=$(datadir)/java
+
+$(FATJAR): classaltosmap.stamp Manifest-fat.txt $(ALTOSLIB_CLASS)
+ jar cfm $@ Manifest-fat.txt \
+ -C classes altosmap
+
+altos-map: Makefile
+ echo "#!/bin/sh" > $@
+ echo 'exec java -Djava.library.path="$(altoslibdir)" -jar "$(altosmapdir)/altosmap.jar" "$$@"' >> $@
+ chmod +x $@
+
+altos-map-test: Makefile
+ echo '#!/bin/sh' > $@
+ echo 'dir="$$(dirname $$0)"' >> $@
+ echo 'cd "$$dir"' >> $@
+ echo 'altosmap="$$(pwd -P)"' >> $@
+ echo 'exec java -jar "$$altosmap/altosmap.jar" "$$@"' >> $@
+ chmod +x $@
+
+altos-map-jdb: Makefile
+ echo "#!/bin/sh" > $@
+ echo 'exec jdb altosmap/AltosMap "$$@"' >> $@
+ chmod +x $@
+
+$(ALTOSLIB_CLASS):
+ -rm -f "$@"
+ $(LN_S) ../../altoslib/"$@" .
+
--- /dev/null
+Main-Class: altosmap.AltosMap
+Class-Path: altoslib_13.jar
--- /dev/null
+#!/bin/sh
+# map-N43.799102,W120.586281-hybrid-20.jpg
+export QUERY_STRING="lat=43.799102&lon=-120.586281&zoom=20"
+export REMOTE_ADDR="127.0.0.1"
+./altos-map-test
+
--- /dev/null
+*.stamp
+*.jar
+altos-mapd
+altos-mapd-jdb
+altos-mapd-test
+classes
--- /dev/null
+/*
+ * Copyright © 2018 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+package altosmapd;
+
+import java.net.*;
+import java.io.*;
+
+import org.altusmetrum.altoslib_13.*;
+
+public class AltosMapd {
+
+ public final static int port = 16717;
+
+ public final static int maptype = AltosMap.maptype_hybrid;
+
+ public final static int px_size = 512;
+
+ public final static int scale = 1;
+
+ public static void main(final String[] args) {
+
+ AltosMapdServer server = new AltosMapdServer(port);
+
+ AltosPreferences.init(new AltosMapdPreferences());
+
+ if (args.length < 1) {
+ System.out.printf("usage: altos-mapd <map-directory>\n");
+ System.exit(1);
+ }
+
+ AltosPreferences.mapdir = new File(args[0]);
+
+ for (;;) {
+ Socket client = server.accept();
+ if (client == null) {
+ System.out.printf("accept failed\n");
+ continue;
+ }
+ System.out.printf("got client\n");
+ new AltosMapdClient(client);
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright © 2018 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+package altosmapd;
+
+import java.net.*;
+import java.util.*;
+import java.util.concurrent.*;
+import java.io.*;
+
+import org.altusmetrum.altoslib_13.*;
+
+public class AltosMapdClient extends Thread implements AltosMapStoreListener {
+ private Socket socket;
+ private AltosJson request;
+ private AltosJson reply;
+
+ private void set_status(int status) {
+ reply.put("status", status);
+ }
+
+ private void set_filename(String filename) {
+ reply.put("filename", filename);
+
+ }
+
+ private void set_content_type(String content_type) {
+ reply.put("content_type", content_type);
+ }
+
+ private String content_type(File file) {
+ String content_type = "application/octet-stream";
+ String basename = file.getName();
+ if (basename.endsWith(".jpg"))
+ content_type = "image/jpeg";
+ if (basename.endsWith(".png"))
+ content_type = "image/png";
+ return content_type;
+ }
+
+ private void set_file(File file) {
+ set_filename(file.getAbsolutePath());
+ set_content_type(content_type(file));
+ }
+
+ private Semaphore store_ready;
+
+ public void notify_store(AltosMapStore map_store, int status) {
+ if (status != AltosMapTile.fetching)
+ store_ready.release();
+ }
+
+ public void run() {
+ reply = new AltosJson();
+ try {
+ request = AltosJson.fromInputStream(socket.getInputStream());
+
+ double lat = request.get_double("lat", AltosLib.MISSING);
+ double lon = request.get_double("lon", AltosLib.MISSING);
+ int zoom = request.get_int("zoom", AltosLib.MISSING);
+ String addr = request.get_string("remote_addr", null);
+
+ if (lat == AltosLib.MISSING ||
+ lon == AltosLib.MISSING ||
+ zoom == AltosLib.MISSING ||
+ addr == null)
+ {
+ set_status(400);
+ } else {
+ store_ready = new Semaphore(0);
+
+ System.out.printf("Fetching tile for %g %g %d\n", lat, lon, zoom);
+
+ AltosMapStore map_store = AltosMapStore.get(new AltosLatLon(lat, lon),
+ zoom,
+ AltosMapd.maptype,
+ AltosMapd.px_size,
+ AltosMapd.scale);
+ int status;
+
+ if (map_store == null) {
+ System.out.printf("no store?\n");
+ status = AltosMapTile.failed;
+ } else {
+ map_store.add_listener(this);
+
+ System.out.printf("Waiting for tile\n");
+
+ try {
+ store_ready.acquire();
+ } catch (Exception ie) {
+ }
+
+ status = map_store.status();
+ }
+
+ if (status == AltosMapTile.fetched || status == AltosMapTile.loaded) {
+ set_status(200);
+ set_file(map_store.file);
+ } else if (status == AltosMapTile.failed) {
+ set_status(404);
+ } else if (status == AltosMapTile.fetching) {
+ set_status(408);
+ } else if (status == AltosMapTile.bad_request) {
+ set_status(400);
+ } else if (status == AltosMapTile.forbidden) {
+ set_status(403);
+ } else {
+ set_status(400);
+ }
+ }
+ } catch (Exception e) {
+ System.out.printf("client exception %s\n", e.toString());
+ e.printStackTrace(System.out);
+ set_status(400);
+
+ } finally {
+ try {
+ Writer writer = new PrintWriter(socket.getOutputStream());
+ reply.write(writer);
+ writer.write('\n');
+ writer.flush();
+ } catch (IOException ie) {
+ }
+ try {
+ socket.close();
+ } catch (IOException ie) {
+ }
+ System.out.printf("client done\n");
+ }
+ }
+
+ public AltosMapdClient(Socket socket) {
+ this.socket = socket;
+ start();
+ }
+}
--- /dev/null
+/*
+ * Copyright © 2018 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+package altosmapd;
+
+import java.io.*;
+
+import org.altusmetrum.altoslib_13.*;
+
+public class AltosMapdPreferences extends AltosPreferencesBackend {
+
+ public String getString(String key, String def) {
+ return def;
+ }
+ public void putString(String key, String value) {
+ }
+
+ public int getInt(String key, int def) {
+ return def;
+ }
+
+ public void putInt(String key, int value) {
+ }
+
+ public double getDouble(String key, double def) {
+ return def;
+ }
+
+ public void putDouble(String key, double value) {
+ }
+
+ public boolean getBoolean(String key, boolean def) {
+ return def;
+ }
+
+ public void putBoolean(String key, boolean value) {
+ }
+
+ public byte[] getBytes(String key, byte[] def) {
+ return def;
+ }
+
+ public void putBytes(String key, byte[] value) {
+ }
+
+ public boolean nodeExists(String key) {
+ return false;
+ }
+
+ public AltosPreferencesBackend node(String key) {
+ return this;
+ }
+
+ public String[] keys() {
+ return null;
+ }
+
+ public void remove(String key) {
+ }
+
+ public void flush() {
+ }
+
+ public File homeDirectory() {
+ return new File (".");
+ }
+
+ public void debug(String format, Object ... arguments) {
+ System.out.printf(format, arguments);
+ }
+
+ public AltosMapdPreferences() {
+ }
+}
--- /dev/null
+/*
+ * Copyright © 2018 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+package altosmapd;
+
+import java.net.*;
+
+public class AltosMapdServer {
+ ServerSocket socket;
+
+ public Socket accept() {
+ try {
+ return socket.accept();
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ public AltosMapdServer(int port) {
+ try {
+ socket = new ServerSocket(port, 5, InetAddress.getLoopbackAddress());
+ } catch (Exception e) {
+ socket = null;
+ }
+ }
+}
--- /dev/null
+JAVAROOT=classes
+AM_JAVACFLAGS=-target 1.6 -encoding UTF-8 -Xlint:deprecation -Xlint:unchecked -source 6
+
+altoslibdir=$(libdir)/altos
+
+CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH="$(JAVAROOT):../../altoslib/*"
+
+bin_SCRIPTS=altos-mapd
+
+altosmapd_JAVA = \
+ AltosMapd.java \
+ AltosMapdServer.java \
+ AltosMapdClient.java \
+ AltosMapdPreferences.java
+
+ALTOSLIB_CLASS=\
+ altoslib_$(ALTOSLIB_VERSION).jar
+
+JAR=altosmapd.jar
+
+FATJAR=altosmapd-fat.jar
+
+all-local: classes/altosmapd $(JAR) altos-mapd altos-mapd-test altos-mapd-jdb
+
+classes/altosmapd:
+ mkdir -p classes/altosmapd
+
+$(JAR): classaltosmapd.stamp Manifest.txt $(ALTOSLIB_CLASS)
+ jar cfm $@ Manifest.txt \
+ -C classes altosmapd
+
+altosmapddir=$(datadir)/java
+
+$(FATJAR): classaltosmapd.stamp Manifest-fat.txt $(ALTOSLIB_CLASS)
+ jar cfm $@ Manifest-fat.txt \
+ -C classes altosmapd
+
+altos-mapd: Makefile
+ echo "#!/bin/sh" > $@
+ echo 'exec java -Djava.library.path="$(altoslibdir)" -jar "$(altosmapddir)/altosmapd.jar" "$$@"' >> $@
+ chmod +x $@
+
+altos-mapd-test: Makefile
+ echo '#!/bin/sh' > $@
+ echo 'dir="$$(dirname $$0)"' >> $@
+ echo 'cd "$$dir"' >> $@
+ echo 'altosmapd="$$(pwd -P)"' >> $@
+ echo 'exec java -jar "$$altosmapd/altosmapd.jar" "$$@"' >> $@
+ chmod +x $@
+
+altos-mapd-jdb: Makefile
+ echo "#!/bin/sh" > $@
+ echo 'exec jdb altosmapd/AltosMapd "$$@"' >> $@
+ chmod +x $@
+
+$(ALTOSLIB_CLASS):
+ -rm -f "$@"
+ $(LN_S) ../../altoslib/"$@" .
+
--- /dev/null
+Main-Class: altosmapd.AltosMapd
+Class-Path: altoslib_13.jar