package edu.kit.pse.ws2013.routekit.mapdisplay; import java.awt.image.BufferedImage; import java.io.IOException; import java.net.HttpURLConnection; import java.net.URL; import java.util.Random; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.imageio.ImageIO; /** * A {@link TileSource} that downloads the tiles from the OpenStreetMap servers. */ public class OSMRenderer implements TileSource { private final Matcher matcher; private final Random random; private final String ext; /** * Creates a new {@link OSMRenderer}. * * @param tileServer * The tile server to use. The string may contain regex-like * groups to account for load balancing, like this: * {@code http://[abc].tile.openstreetmap.org/} * @throws IOException * If the server can’t be reached. */ public OSMRenderer(String tileServer) throws IOException { if (tileServer == null) { throw new IllegalArgumentException("tileServer must not be null!"); } if (!tileServer.endsWith("/")) { tileServer += "/"; } matcher = Pattern.compile("\\[[^\\]]+\\]").matcher(tileServer); random = new Random(); // find out what extension we need // try .png first URL uPng = new URL(getTileServer() + "0/0/0.png"); HttpURLConnection cPng = (HttpURLConnection) uPng.openConnection(); cPng.setRequestMethod("HEAD"); // we’re not interested in the content cPng.connect(); if (cPng.getResponseCode() == 200 /* OK */) { ext = ".png"; } else { // try .jpg instead URL uJpg = new URL(getTileServer() + "0/0/0.jpg"); HttpURLConnection cJpg = (HttpURLConnection) uJpg.openConnection(); cJpg.setRequestMethod("HEAD"); cJpg.connect(); if (cJpg.getResponseCode() == 200) { ext = ".jpg"; } else { throw new IOException( "No tiles found with .jpg or .png suffixes!"); } } } private synchronized String getTileServer() { final StringBuffer s = new StringBuffer(); while (matcher.find()) { // choose a random item to transform // [abcd].server.com into // c.server.com final String group = matcher.group(); final String characters = group.substring(1, group.length() - 1); matcher.appendReplacement( s, new String(new char[] { characters.charAt(random .nextInt(characters.length())) })); } matcher.appendTail(s); matcher.reset(); return s.toString(); } /** * Downloads the given tile and returns it. * * @param x * The SMT X coordinate of the requested tile. * @param y * The SMT Y coordinate of the requested tile. * @param zoom * The zoom of the requested tile. * @param tile * The downloaded tile. */ @Override public BufferedImage renderTile(int x, int y, int zoom) { if (zoom > 19 || zoom < 0) { return null; } try { URL url = new URL(getTileServer() + zoom + "/" + x + "/" + y + ext); HttpURLConnection huc = ((HttpURLConnection) url.openConnection()); huc.setRequestProperty("User-Agent", "routeKit/1.0 (study project)"); return ImageIO.read(huc.getInputStream()); } catch (IOException e) { e.printStackTrace(); } return null; } }