mirror of https://github.com/webbukkit/dynmap.git
187 lines
6.8 KiB
Java
187 lines
6.8 KiB
Java
package org.dynmap.servlet;
|
|
|
|
import org.dynmap.DynmapCore;
|
|
import org.dynmap.DynmapWorld;
|
|
import org.dynmap.MapType.ImageEncoding;
|
|
import org.dynmap.PlayerFaces;
|
|
import org.dynmap.storage.MapStorage;
|
|
import org.dynmap.storage.MapStorageTile;
|
|
import org.dynmap.storage.MapStorageTile.TileRead;
|
|
import org.dynmap.utils.BufferInputStream;
|
|
import org.eclipse.jetty.http.HttpStatus;
|
|
import org.eclipse.jetty.server.Request;
|
|
import org.eclipse.jetty.server.handler.AbstractHandler;
|
|
|
|
import javax.imageio.ImageIO;
|
|
import javax.servlet.ServletException;
|
|
import javax.servlet.ServletOutputStream;
|
|
import javax.servlet.http.HttpServletRequest;
|
|
import javax.servlet.http.HttpServletResponse;
|
|
|
|
import java.awt.image.BufferedImage;
|
|
import java.io.ByteArrayOutputStream;
|
|
import java.io.IOException;
|
|
import java.io.PrintWriter;
|
|
import java.io.OutputStream;
|
|
|
|
public class MapStorageResourceHandler extends AbstractHandler {
|
|
|
|
private DynmapCore core;
|
|
private byte[] blankpng;
|
|
private long blankpnghash = 0x12345678;
|
|
|
|
public MapStorageResourceHandler() {
|
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
|
BufferedImage blank = new BufferedImage(128, 128, BufferedImage.TYPE_INT_ARGB);
|
|
try {
|
|
ImageIO.write(blank, "png", baos);
|
|
blankpng = baos.toByteArray();
|
|
} catch (IOException e) {
|
|
}
|
|
|
|
}
|
|
@Override
|
|
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
|
|
String path = baseRequest.getPathInfo();
|
|
int soff = 0, eoff;
|
|
// We're handling this request
|
|
baseRequest.setHandled(true);
|
|
if(core.getLoginRequired()
|
|
&& request.getSession(true).getAttribute(LoginServlet.USERID_ATTRIB) == null){
|
|
response.sendError(HttpStatus.UNAUTHORIZED_401);
|
|
return;
|
|
}
|
|
if (path.charAt(0) == '/') soff = 1;
|
|
eoff = path.indexOf('/', soff);
|
|
if (soff < 0) {
|
|
response.sendError(HttpStatus.NOT_FOUND_404);
|
|
return;
|
|
}
|
|
String world = path.substring(soff, eoff);
|
|
String uri = path.substring(eoff+1);
|
|
// If faces directory, handle faces
|
|
if (world.equals("faces")) {
|
|
handleFace(response, uri);
|
|
return;
|
|
}
|
|
// If markers directory, handle markers
|
|
if (world.equals("_markers_")) {
|
|
handleMarkers(response, uri);
|
|
return;
|
|
}
|
|
|
|
DynmapWorld w = null;
|
|
if (core.mapManager != null) {
|
|
w = core.mapManager.getWorld(world);
|
|
}
|
|
// If world not found quit
|
|
if (w == null) {
|
|
response.setContentType("image/png");
|
|
OutputStream os = response.getOutputStream();
|
|
os.write(blankpng);
|
|
return;
|
|
}
|
|
MapStorage store = w.getMapStorage(); // Get storage handler
|
|
// Get tile reference, based on URI and world
|
|
MapStorageTile tile = store.getTile(w, uri);
|
|
if (tile == null) {
|
|
response.setContentType("image/png");
|
|
OutputStream os = response.getOutputStream();
|
|
os.write(blankpng);
|
|
return;
|
|
}
|
|
// Read tile
|
|
TileRead tr = null;
|
|
if (tile.getReadLock(5000)) {
|
|
tr = tile.read();
|
|
tile.releaseReadLock();
|
|
}
|
|
response.setHeader("Cache-Control", "max-age=0,must-revalidate");
|
|
String etag;
|
|
if (tr == null) {
|
|
etag = "\"" + blankpnghash + "\"";
|
|
}
|
|
else {
|
|
etag = "\"" + tr.hashCode + "\"";
|
|
}
|
|
response.setHeader("ETag", etag);
|
|
String ifnullmatch = request.getHeader("If-None-Match");
|
|
if ((ifnullmatch != null) && ifnullmatch.equals(etag)) {
|
|
response.sendError(HttpStatus.NOT_MODIFIED_304);
|
|
return;
|
|
}
|
|
if (tr == null) {
|
|
response.setContentType("image/png");
|
|
response.setIntHeader("Content-Length", blankpng.length);
|
|
OutputStream os = response.getOutputStream();
|
|
os.write(blankpng);
|
|
return;
|
|
}
|
|
// Got tile, package up for response
|
|
response.setDateHeader("Last-Modified", tr.lastModified);
|
|
response.setIntHeader("Content-Length", tr.image.length());
|
|
response.setContentType(tr.format.getContentType());
|
|
ServletOutputStream out = response.getOutputStream();
|
|
out.write(tr.image.buffer(), 0, tr.image.length());
|
|
out.flush();
|
|
|
|
}
|
|
|
|
private void handleFace(HttpServletResponse response, String uri) throws IOException, ServletException {
|
|
String[] suri = uri.split("[/\\.]");
|
|
if (suri.length < 3) { // 3 parts : face ID, player name, png
|
|
response.sendError(HttpStatus.NOT_FOUND_404);
|
|
return;
|
|
}
|
|
// Find type
|
|
PlayerFaces.FaceType ft = PlayerFaces.FaceType.byID(suri[0]);
|
|
if (ft == null) {
|
|
response.sendError(HttpStatus.NOT_FOUND_404);
|
|
return;
|
|
}
|
|
BufferInputStream bis = null;
|
|
if (core.playerfacemgr != null) {
|
|
bis = core.playerfacemgr.storage.getPlayerFaceImage(suri[1], ft);
|
|
}
|
|
if (bis == null) {
|
|
response.sendError(HttpStatus.NOT_FOUND_404);
|
|
return;
|
|
}
|
|
// Got image, package up for response
|
|
response.setIntHeader("Content-Length", bis.length());
|
|
response.setContentType("image/png");
|
|
ServletOutputStream out = response.getOutputStream();
|
|
out.write(bis.buffer(), 0, bis.length());
|
|
out.flush();
|
|
}
|
|
|
|
private void handleMarkers(HttpServletResponse response, String uri) throws IOException, ServletException {
|
|
String[] suri = uri.split("/");
|
|
// If json file in last part
|
|
if ((suri.length == 1) && suri[0].startsWith("marker_") && suri[0].endsWith(".json")) {
|
|
String content = core.getDefaultMapStorage().getMarkerFile(suri[0].substring(7, suri[0].length() - 5));
|
|
response.setContentType("application/json");
|
|
PrintWriter pw = response.getWriter();
|
|
pw.print(content);
|
|
pw.flush();
|
|
return;
|
|
}
|
|
// If png, make marker ID
|
|
if (suri[suri.length-1].endsWith(".png")) {
|
|
BufferInputStream bis = core.getDefaultMapStorage().getMarkerImage(uri.substring(0, uri.length()-4));
|
|
// Got image, package up for response
|
|
response.setIntHeader("Content-Length", bis.length());
|
|
response.setContentType("image/png");
|
|
ServletOutputStream out = response.getOutputStream();
|
|
out.write(bis.buffer(), 0, bis.length());
|
|
out.flush();
|
|
return;
|
|
}
|
|
response.sendError(HttpStatus.NOT_FOUND_404);
|
|
}
|
|
|
|
public void setCore(DynmapCore core) {
|
|
this.core = core;
|
|
}
|
|
}
|