/*
* $Id$
* $URL$
*/
package org.subethamail.web.servlet;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.extern.java.Log;
import org.subethamail.entity.i.Permission;
/**
* Servlet generates and returns a reasonably nice PNG image
* that describes the permission. This is needed so that we can
* display vertical text. Unfortunately there is not yet any
* web-standard way of doing so.
*
* There are only a few permissions so we cache the PNG images
* in memory.
*
* Parameters expected:
*
* perm: the permission name
*/
@Log
public class PermissionImageServlet extends HttpServlet
{
private static final long serialVersionUID = 1L;
/** */
public static final String PERMISSION_PARAM = "perm";
/** TODO: figure out the img size dynamically */
public static final int IMG_WIDTH = 35;
public static final int IMG_HEIGHT = 140;
/** */
public static final double TEXT_ANGLE_RADIANS = -Math.PI/2.2;
/**
*/
protected Map<Permission, ByteArrayOutputStream> imageCache =
new ConcurrentHashMap<Permission, ByteArrayOutputStream>();
/* (non-Javadoc)
* @see javax.servlet.http.HttpServlet#service(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
if (log.isLoggable(Level.FINE))
log.log(Level.FINE,"Servicing {0}", request.getRequestURI());
String permString = request.getParameter(PERMISSION_PARAM);
Permission perm = Permission.valueOf(permString);
ByteArrayOutputStream cachedStream = this.imageCache.get(perm);
if (cachedStream == null)
{
if (log.isLoggable(Level.INFO))
log.log(Level.INFO,"Cache miss; building image for {0}", perm);
Image img = this.buildImage(perm);
cachedStream = new ByteArrayOutputStream(2048); // is 2k enough?
ImageIO.write((RenderedImage)img, "png", cachedStream);
this.imageCache.put(perm, cachedStream);
}
// And send back the results!
response.setContentType("image/png");
response.setHeader("Cache-Control", "public, max-age=360000");
cachedStream.writeTo(response.getOutputStream());
}
/**
* Build the permission image.
*/
protected Image buildImage(Permission perm) throws ServletException, IOException
{
Graphics2D g = null;
try
{
Image img = new BufferedImage(IMG_WIDTH, IMG_HEIGHT, BufferedImage.TYPE_INT_RGB);
g = (Graphics2D)img.getGraphics();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
// TODO: why doesn't this work?
// Lay down the background as transparent (or at least try to)
//g.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR, 0.0f));
// Just white background instead
g.setColor(Color.WHITE);
g.fillRect(0, 0, IMG_WIDTH, IMG_HEIGHT);
// Now draw text at a diagonal angle from bottom left to top right.
// TODO: remove the black magic constants
g.setColor(Color.BLACK);
g.translate(IMG_WIDTH-25, IMG_HEIGHT);
g.rotate(TEXT_ANGLE_RADIANS);
g.drawString(perm.getPretty(), 0, 0);
return img;
}
finally
{
if (g != null)
g.dispose();
}
}
}