package com.aerodynelabs.map; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.util.concurrent.ConcurrentLinkedQueue; import javax.imageio.ImageIO; /** * A class to download map images from a webserver. * @author Ethan Harstad * */ public class TileServer extends Thread { //private static final int TILE_SIZE = 256; private String url; private boolean OFFLINE = false; private int maxZoom; private final MapPanel client; private TileCache cache; private TileStore store; private ConcurrentLinkedQueue<Tile> queue; private boolean alive; private static BufferedImage dTile; private static BufferedImage zTile; private static BufferedImage nTile; public TileServer(MapPanel client) { this("http://tile.openstreetmap.org/", 18, client); } public TileServer(String url, MapPanel client) { this(url, 17, client); } public TileServer(String url, int maxZoom, MapPanel client) { this.client = client; this.url = url; this.maxZoom = maxZoom; cache = new TileCache(); String name = url.replaceAll("http://", ""); name = name.replaceAll("[./\\\\]", "_"); name = name.replaceAll("[^a-zA-Z0-9_]", ""); store = new TileStore(name); queue = new ConcurrentLinkedQueue<Tile>(); alive = true; this.start(); loadResources(); } /** * Load local resources */ private void loadResources() { try { dTile = ImageIO.read(new File("resources/loadingTile.png")); zTile = ImageIO.read(new File("resources/zoomTile.png")); nTile = ImageIO.read(new File("resources/noTile.png")); } catch (IOException e) { e.printStackTrace(); } } /** * Close the server connection */ public void close() { alive = false; queue.clear(); } /** * Get the name of a time * @param tile * @return */ protected static String getTileName(Tile tile) { return tile.getZoom() + "/" + tile.getX() + "/" + tile.getY() + ".png"; } /** * Get the address of a time * @param tile * @return */ private String getTileAddress(Tile tile) { return url + getTileName(tile); } /** * Get tile image from cache or local store or server (in that order). * @param x * @param y * @param zoom * @return */ protected synchronized BufferedImage getTile(int x, int y, int zoom) { if(zoom > maxZoom) return zTile; if( x < 0 || y < 0 || x > (1 << zoom) || y > (1 << zoom) ) return nTile; BufferedImage image = null; Tile tile = new Tile(x, y, zoom); //System.out.println(getTileName(tile)); // Check cache image = cache.get(tile); if(image != null) { //System.out.println("Found in Cache"); return image; } // Check store image = store.get(tile); if(image != null) { //System.out.println("Found in Store"); cache.put(tile, image); // Check if image is out of date if(!OFFLINE) { if(store.isOld(tile)) { if(!queue.contains(tile)) { queue.add(tile); } } } return image; } // Download if(!OFFLINE) { if(!queue.contains(tile)) { //System.out.println("Added " + tile); queue.add(tile); } this.notify(); } return dTile; } protected int getMaxZoom() { return maxZoom; } /** * Start the download manager thread */ public void run() { while(alive) { // try { // InetAddress addr = InetAddress.getByName("www.google.com"); // OFFLINE = !addr.isReachable(250); // } catch (Exception e1) { // OFFLINE = true; // e1.printStackTrace(); // } // System.out.println(OFFLINE); while(!queue.isEmpty() && !OFFLINE) { Tile tile = queue.poll(); //System.out.println("Getting " + tile); BufferedImage image = null; try { image = ImageIO.read(new URL(getTileAddress(tile))); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } if(image != null) { store.put(tile, image); client.updateNotify(); } } try { synchronized(this) { // System.out.println("Waiting"); wait(500); } } catch (InterruptedException e) { e.printStackTrace(); } } } }