PlaceMapServlet.java 10.3 KB
/*
 * Copyright Codecrew Ry
 * 
 * All rights reserved.
 * 
 * This license applies to any software containing a notice placed by the 
 * copyright holder. Such software is herein referred to as the Software. 
 * This license covers modification, distribution and use of the Software. 
 * 
 * Any distribution and use in source and binary forms, with or without 
 * modification is not permitted without explicit written permission from the 
 * copyright owner. 
 * 
 * A non-exclusive royalty-free right is granted to the copyright owner of the 
 * Software to use, modify and distribute all modifications to the Software in 
 * future versions of the Software. 
 * 
 */
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package fi.codecrew.moya.servlet;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.ejb.EJB;
import javax.ejb.EJBAccessException;
import javax.ejb.EJBException;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import fi.codecrew.moya.beans.*;
import fi.codecrew.moya.model.User;
import org.primefaces.component.barcode.Barcode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import fi.codecrew.moya.enums.apps.MapPermission;
import fi.codecrew.moya.model.EventMap;
import fi.codecrew.moya.model.EventUser;
import fi.codecrew.moya.model.Place;
import fi.codecrew.moya.utilities.moyamessage.MoyaEventType;

/**
 * 
 * @author tuukka
 */
@WebServlet("/PlaceMap")
public class PlaceMapServlet extends HttpServlet {

	private static final Logger logger = LoggerFactory.getLogger(PlaceMapServlet.class);

	private static final long serialVersionUID = 8769688627918936258L;
	@EJB
	private transient PlaceBeanLocal placeBean;

	@EJB
	private transient PermissionBeanLocal permbean;

	@EJB
	private transient LoggingBeanLocal loggerbean;

	@EJB
	private UserBeanLocal userBean;

	@EJB
	private BarcodeBeanLocal barcodeBean;

	private static final String PARAMETER_EVENT_MAP_ID = "mapid";
	private static final String PARAMETER_USER_ID = "userid";
	private static final String PARAMETER_TOKEN = "token";


	/**
	 * Processes requests for both HTTP <code>GET</code> and <code>POST</code>
	 * methods.
	 * 
	 * @param request
	 *            servlet request
	 * @param response
	 *            servlet response
	 * @throws ServletException
	 *             if a servlet-specific error occurs
	 * @throws IOException
	 *             if an I/O error occurs
	 */
	protected void processRequest(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		logger.debug("Begin processing request");
		// response.setContentType("text/html;charset=UTF-8");

		// PrintWriter out = response.getWriter();
		ServletOutputStream ostream = null;
		try {
			// Integer placeId = getIntegerParameter(request,
			// PARAMETER_SELECTED_PLACE_ID);

			Integer mapId = getIntegerParameter(request, PARAMETER_EVENT_MAP_ID);

			Integer userId = getIntegerParameter(request, PARAMETER_USER_ID);

			String userToken = request.getParameter(PARAMETER_TOKEN);




			EventMap map = placeBean.findMap(mapId);
			logger.debug("Mapid: {}", mapId);
			ostream = response.getOutputStream();

			if (map == null || map.getMapData() == null) {
				logger.warn("Error handling map {}!", map);
				response.setStatus(HttpServletResponse.SC_NOT_FOUND);
				ostream.print("Map error!");

			} else {


				String[] splittype = map.getMimeType().split("/");
				String type = "png";

				if(splittype.length > 0)
					type = splittype[splittype.length-1];

				response.setContentType(map.getMimeType());
				printPlaceMapToStream(ostream, type, map,userId, userToken);
				logger.debug("Flushing ostream");
				ostream.flush();
			}

		} catch (EJBException e) {


			logger.debug("Permission denied. Returning SC_FORBIDDEN!");
			response.setContentType("text/html;charset=UTF-8");
			response.setStatus(HttpServletResponse.SC_FORBIDDEN);
			ostream = response.getOutputStream();
			ostream.print("Error 403 \nPermission denied! Please login before accessing resource");
	//		e.printStackTrace();

		} finally {
			if (ostream != null) {
				ostream.close();
			}
		}
	}

	private void printPlaceMapToStream(OutputStream outputStream, String filetype, EventMap map, Integer userid, String userToken) throws IOException
	{


		EventUser user = null;
		if(userToken != null)
			user = barcodeBean.getUserFromLongTextCode(userToken);


		if (!permbean.hasPermission(MapPermission.VIEW) && user == null)
		{
			loggerbean.sendMessage(MoyaEventType.USER_INSUFFICIENT_PERMISSIONS, permbean.getCurrentUser(), "User tried to print the placemap to stream without sufficient permissions");
			throw new EJBAccessException("Not enough permissions to print placemap");
		}
		long begin = new Date().getTime();

		// List<Place> selectedPlaceList = placeBean.findPlaces(placeIds);

		// logger.debug("SelectedPlaceList: size {}, {} ",
		// selectedPlaceList.size(), selectedPlaceList);

		// map = eventMapFacade.find(eventId, mapId);

		// if (map == null) {
		// throw new PermissionDeniedException(secubean, user,
		// "Map not found with id: " + mapId + " and event id: " +
		// eventbean.getCurrentEvent());
		// }

		// logger.debug("Got map object {}", map);
		List<Place> places = map.getPlaces();
		List<Place> userplaces = null;


		if(userid != null && userid != 0) {
			EventUser placesForUser = userBean.findByUserId(userid, false);

			if(user != null) {
				userplaces = placeBean.findPlacePrintlistForUser(placesForUser);
			}
		}

		if(user != null) {
			userplaces = placeBean.findPlacePrintlistForUser(user);
		}


		if(user == null)
			user = permbean.getCurrentUser();
		// List<Place> selectedPlaces = placemapBean.findSelectedPlaces(map);

		BufferedImage image = ImageIO.read(new ByteArrayInputStream(map.getMapData()));

		Graphics2D g2d = image.createGraphics();
		for (Place place : places) {
			if(userplaces != null) {
				if(userplaces.contains(place)) {
					drawPlace(place, g2d, user, true, true);
				} else {
					drawPlace(place, g2d, user, true, false);
				}

			} else {
				drawPlace(place, g2d, user, false, false);
			}
		}

		// BufferedImage image = map.getMapWithPlaces(, selectedPlaces);

		logger.debug("Prewrite {}", new Date().getTime() - begin);
		ImageIO.write(image, filetype, outputStream);
		logger.debug("postwrite {}", new Date().getTime() - begin);

	}

	/***
	 * Convert request parameter into integer
	 * 
	 * @param request
	 * @param parameter
	 * @return
	 */
	private static Integer getIntegerParameter(HttpServletRequest request,
			String parameter) {
		try {
			String valueString = request.getParameter(parameter);
			Integer value = Integer.parseInt(valueString);
			return value;
		} catch (NumberFormatException nfe) {
		}
		return null;
	}


	// <editor-fold defaultstate="collapsed"
	// desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
	/**
	 * Handles the HTTP <code>GET</code> method.
	 * 
	 * @param request
	 *            servlet request
	 * @param response
	 *            servlet response
	 * @throws ServletException
	 *             if a servlet-specific error occurs
	 * @throws IOException
	 *             if an I/O error occurs
	 */
	@Override
	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		processRequest(request, response);
	}

	/**
	 * Handles the HTTP <code>POST</code> method.
	 * 
	 * @param request
	 *            servlet request
	 * @param response
	 *            servlet response
	 * @throws ServletException
	 *             if a servlet-specific error occurs
	 * @throws IOException
	 *             if an I/O error occurs
	 */
	@Override
	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		processRequest(request, response);
	}

	/**
	 * Returns a short description of the servlet.
	 * 
	 * @return a String containing servlet description
	 */
	@Override
	public String getServletInfo() {
		return "Short description";
	}// </editor-fold>

	private static final Color RESERVED_COLOR = Color.RED;
	private static final Color SELECTED_COLOR = Color.BLUE;
	private static final Color OWNED_COLOR = Color.GREEN;
	private static final Color BORDER_COLOR = Color.BLACK;
	private static final Color LOCKED_COLOR = Color.DARK_GRAY;

	private static void drawPlace(Place p, Graphics2D g, EventUser user, boolean onlyFrame, boolean hilight) {
		if (p.isDisabled()) {
			return;
		}
		Color color = null;

		if(!onlyFrame) {
			if (!p.isBuyable()) {
				logger.debug("Setting color as locked place.");
				color = LOCKED_COLOR;
			}

			if (p.isReservedFor(user)) {
				//			logger.debug("Setting place selected {}", p);
				color = SELECTED_COLOR;
			} else if (user.equals(p.getCurrentUser())
					|| (p.getGroup() != null && user.equals(p.getGroup().getCreator()))
					|| (p.getPlaceReserver() != null && user.equals(p
					.getPlaceReserver().getUser()))) {
				color = OWNED_COLOR;
				//		logger.debug("Setting place owned {}", p);

			} else if (p.isTaken()) {
				color = RESERVED_COLOR;
				//	logger.debug("Setting place Reserved {}", p);

			} else if (p.getProduct() != null && p.getProduct() != null && p.getProduct().getColor() != null && !p.getProduct().getColor().isEmpty()) {
				try {
					color = Color.decode(p.getProduct().getColor());
				} catch (NumberFormatException x) {
					logger.error("Cannot convert string {} to color.", p.getProduct().getColor());
				}
			} else {
				// 			too much debugging -TKjne
				//			logger.debug("Nothing special for this place. Color should be default.");

			}
		}

		if(hilight) {
			color = OWNED_COLOR;
		}

		if (color != null) {
			//logger.debug("Setting fill color: {} for p", color, p);
			g.setColor(color);
			g.fill(new Rectangle(p.getMapX()+1, p.getMapY()+1, p.getWidth()-1, p.getHeight()-1));
		}

		g.setColor(BORDER_COLOR);
		g.draw(new Rectangle(p.getMapX(), p.getMapY(), p.getWidth(), p.getHeight()));
	}
}