package mobac.mapsources.custom;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import javax.imageio.ImageIO;
import mobac.exceptions.TileException;
import mobac.exceptions.UnrecoverableDownloadException;
import mobac.gui.mapview.PreviewMap;
import mobac.mapsources.AbstractHttpMapSource;
import mobac.mapsources.mapspace.MapSpaceFactory;
import mobac.program.interfaces.MapSpace;
import mobac.program.interfaces.MapSource.LoadMethod;
import mobac.program.interfaces.MapSpace.MapSpaceType;
import mobac.program.jaxb.ColorAdapter;
import mobac.program.model.TileImageType;
import mobac.utilities.Charsets;
import mobac.utilities.Utilities;
import bsh.EvalError;
import bsh.Interpreter;
public class BeanShellHttpMapSource extends AbstractHttpMapSource {
private static final String AH_ERROR = "Sourced file: inline evaluation of: "
+ "``addHeaders(conn);'' : Command not found: addHeaders( sun.net.www.protocol.http.HttpURLConnection )";
private static int NUM = 0;
private final Interpreter i;
private Color backgroundColor = Color.BLACK;
private boolean ignoreErrors = false;
private boolean hiddenDefault = false;
public static BeanShellHttpMapSource load(File f) throws EvalError, IOException {
FileInputStream in = new FileInputStream(f);
try {
BufferedReader br = new BufferedReader(new InputStreamReader(in, Charsets.UTF_8));
StringWriter sw = new StringWriter();
String line = br.readLine();
while (line != null) {
sw.write(line + "\n");
line = br.readLine();
}
br.close();
return new BeanShellHttpMapSource(sw.toString());
} finally {
Utilities.closeStream(in);
}
}
public BeanShellHttpMapSource(String code) throws EvalError {
super("", 0, 0, TileImageType.PNG, TileUpdate.None);
name = "BeanShell map source " + NUM++;
i = new Interpreter();
i.eval("import mobac.program.interfaces.HttpMapSource.TileUpdate;");
i.eval("import java.net.HttpURLConnection;");
i.eval("import mobac.utilities.beanshell.*;");
i.eval("import mobac.program.interfaces.MapSpace.MapSpaceType");
i.eval(code);
Object o = i.get("name");
if (o != null)
name = (String) o;
MapSpaceType mapSpaceType = MapSpaceType.msMercatorSpherical;
o = i.get("mapSpaceType");
if (o != null)
mapSpaceType = (MapSpaceType) o;
int tileSize = 256;
o = i.get("tileSize");
if (o != null)
tileSize = ((Integer) o).intValue();
mapSpace = MapSpaceFactory.getInstance(tileSize, mapSpaceType);
o = i.get("minZoom");
if (o != null)
minZoom = ((Integer) o).intValue();
else
minZoom = 0;
o = i.get("maxZoom");
if (o != null)
maxZoom = ((Integer) o).intValue();
else
maxZoom = PreviewMap.MAX_ZOOM;
o = i.get("tileType");
if (o != null)
tileType = TileImageType.getTileImageType((String) o);
else
throw new EvalError("tileType definition missing", null, null);
o = i.get("tileUpdate");
if (o != null)
tileUpdate = (TileUpdate) o;
o = i.get("ignoreError");
if (o == null) o = i.get("ignoreErrors");
if (o != null) {
if (o instanceof String) {
ignoreErrors = Boolean.parseBoolean((String) o);
} else if (o instanceof Boolean) {
ignoreErrors = ((Boolean) o).booleanValue();
} else
throw new EvalError("Invalid type for \"ignoreError(s)\": " + o.getClass(), null, null);
}
o = i.get("backgroundColor");
if (o != null)
try {
backgroundColor = ColorAdapter.parseColor((String) o);
} catch (javax.xml.bind.UnmarshalException e) {
throw new EvalError(e.getMessage(), null, null);
}
o = i.get("hiddenDefault");
if (o != null) {
if (o instanceof String) {
hiddenDefault = Boolean.parseBoolean((String) o);
} else if (o instanceof Boolean) {
hiddenDefault = ((Boolean) o).booleanValue();
}
}
}
@Override
public synchronized HttpURLConnection getTileUrlConnection(int zoom, int tilex, int tiley) throws IOException {
HttpURLConnection conn = null;
try {
String url = getTileUrl(zoom, tilex, tiley);
conn = (HttpURLConnection) new URL(url).openConnection();
} catch (IOException e) {
throw e;
} catch (Exception e) {
log.error("", e);
throw new IOException(e);
}
try {
i.set("conn", conn);
i.eval("addHeaders(conn);");
} catch (EvalError e) {
String msg = e.getMessage();
if (!AH_ERROR.equals(msg)) {
log.error(e.getClass() + ": " + e.getMessage(), e);
throw new IOException(e);
}
}
return conn;
}
@Override
public byte[] getTileData(int zoom, int x, int y, LoadMethod loadMethod) throws IOException, TileException,
InterruptedException {
if (!ignoreErrors)
return super.getTileData(zoom, x, y, loadMethod);
try {
return super.getTileData(zoom, x, y, loadMethod);
} catch (Exception e) {
return null;
}
}
@Override
public BufferedImage getTileImage(int zoom, int x, int y, LoadMethod loadMethod) throws IOException, TileException, InterruptedException {
byte[] data = getTileData(zoom, x, y, loadMethod);
if (data == null) {
if (!ignoreErrors)
return null;
else {
int tileSize = this.getMapSpace().getTileSize();
BufferedImage image = new BufferedImage(tileSize, tileSize, BufferedImage.TYPE_4BYTE_ABGR);
Graphics g = (Graphics) image.getGraphics();
try {
g.setColor(backgroundColor);
g.fillRect(0, 0, tileSize, tileSize);
} finally {
g.dispose();
}
return image;
}
} else {
return ImageIO.read(new ByteArrayInputStream(data));
}
}
public boolean testCode() throws IOException {
return (getTileUrlConnection(minZoom, 0, 0) != null);
}
public String getTileUrl(int zoom, int tilex, int tiley) {
try {
return (String) i.eval(String.format("getTileUrl(%d,%d,%d);", zoom, tilex, tiley));
} catch (EvalError e) {
log.error(e.getClass() + ": " + e.getMessage(), e);
throw new RuntimeException(e);
}
}
@Override
public MapSpace getMapSpace() {
return mapSpace;
}
@Override
public int getMaxZoom() {
return maxZoom;
}
@Override
public int getMinZoom() {
return minZoom;
}
@Override
public String getName() {
return name;
}
@Override
public TileUpdate getTileUpdate() {
return tileUpdate;
}
public Color getBackgroundColor() {
return backgroundColor;
}
@Override
public boolean getHiddenDefault() {
return hiddenDefault;
}
}