package com.iambookmaster.server;
import java.io.IOException;
import java.io.StringReader;
import javax.jdo.PersistenceManager;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;
import com.iambookmaster.client.ServerExchangePanel;
import com.iambookmaster.client.common.Base64Coder;
import com.iambookmaster.client.common.JSONBuilder;
import com.iambookmaster.client.editor.ModelPersist;
import com.iambookmaster.client.locale.AppConstants;
import com.iambookmaster.client.locale.AppMessages;
import com.iambookmaster.client.remote.RemotePanel;
import com.iambookmaster.server.beans.JPABook;
import com.iambookmaster.server.beans.JPAUser;
import com.iambookmaster.server.dao.DAO;
public abstract class AbstractServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public JPAUser getUser(HttpServletRequest req,HttpServletResponse resp) throws LogicException {
//for Google App Engines
UserService userService = UserServiceFactory.getUserService();
if (userService.isUserLoggedIn()) {
User usr = userService.getCurrentUser();
PersistenceManager em = getPM(req);
JPAUser user = DAO.getUsersDAO().findOrCreateUser(em, usr);
if (user != null && user.isLocked()) {
//this book is locked
throw new LogicException(getAppConstants(req,resp).serverAccountLocked());
}
return user;
} else {
throw new LogicException(getAppConstants(req,resp).serverNotLoggedIn());
}
}
protected AppConstants getAppConstants(HttpServletRequest req,HttpServletResponse resp) {
return LocalMessages.getInstance(AppConstants.class, LocalMessages.getLocale(req,resp));
}
protected AppMessages getAppMessages(HttpServletRequest req,HttpServletResponse resp) {
return LocalMessages.getInstance(AppMessages.class, LocalMessages.getLocale(req,resp));
}
protected PersistenceManager getPM(ServletRequest req) {
return TransactionInViewFilter.getEM(req);
}
protected void replyError(String error, HttpServletRequest req, HttpServletResponse resp) throws IOException {
String callback = extractCallback(req);
if (callback==null) {
//no callback, just print it
printCallbackError(resp);
return;
}
JSONBuilder builder = JSONBuilder.getStartInstance();
builder.newRow();
builder.field(RemotePanel.FIELD_ANSWER_CODE, RemotePanel.CODE_ERROR);
builder.field(RemotePanel.FIELD_ERROR_SHORT, error);
sendReply(req,resp,callback,builder);
}
protected void replyError(String error, String errorDescription, HttpServletRequest req, HttpServletResponse resp) throws IOException {
String callback = extractCallback(req);
if (callback==null) {
//no callback, just print it
printCallbackError(resp);
return;
}
JSONBuilder builder = JSONBuilder.getStartInstance();
builder.newRow();
builder.field(RemotePanel.FIELD_ANSWER_CODE, RemotePanel.CODE_ERROR);
builder.field(RemotePanel.FIELD_ERROR_SHORT, error);
builder.field(RemotePanel.FIELD_DESCRIPTION, errorDescription.replace("\n", "<br/>"));
sendReply(req,resp,callback,builder);
}
protected void replyError(Throwable error, HttpServletRequest req, HttpServletResponse resp) throws IOException {
StringBuffer buffer = new StringBuffer();
buffer.append(error.getMessage());
buffer.append('\n');
StackTraceElement[] elements = error.getStackTrace();
for (int i = 0; i < elements.length; i++) {
buffer.append(elements[i].toString());
buffer.append('\n');
}
replyError(error.getMessage(),buffer.toString(),req,resp);
}
private void sendReply(HttpServletRequest req,HttpServletResponse resp, String callback, JSONBuilder builder) throws IOException{
resp.setCharacterEncoding("UTF-8");
resp.setContentType("text/html; charset=UTF-8");
resp.getWriter().println("<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>");
resp.getWriter().println("<title>I am Book Master</title>");
resp.getWriter().println("<script language='javascript'>function onloadEvent() {");
resp.getWriter().print("window.name='");
resp.getWriter().print(Base64Coder.encodeString(builder.toString()));
resp.getWriter().println("';");
resp.getWriter().print("try{");
resp.getWriter().print("window.location.href='");
resp.getWriter().print(callback);
resp.getWriter().print("';}catch(e){history.back();return false;}}");
resp.getWriter().println("</script></head><body onload=\"onloadEvent();\"> </body></html>");
resp.flushBuffer();
}
private void printCallbackError(HttpServletResponse resp) throws IOException {
resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "No callback to the client provided");
}
private String extractCallback(HttpServletRequest req) {
String cl = req.getParameter(RemotePanel.FIELD_CALLBACK);
if (cl==null) {
return null;
} else {
try {
return Base64Coder.decodeString(cl);
} catch (Exception e) {
//wrong Base64
return null;
}
}
}
protected void replyOk(HttpServletRequest req, HttpServletResponse resp) throws IOException{
String callback = extractCallback(req);
if (callback==null) {
//no callback, just print it
printCallbackError(resp);
return;
}
JSONBuilder builder = JSONBuilder.getStartInstance();
builder.newRow();
builder.field(RemotePanel.FIELD_ANSWER_CODE, RemotePanel.CODE_SUCCESS);
sendReply(req,resp,callback,builder);
}
protected void replyOk(String url,HttpServletRequest req, HttpServletResponse resp) throws IOException {
String callback = extractCallback(req);
if (callback==null) {
//no callback, just print it
printCallbackError(resp);
return;
}
JSONBuilder builder = JSONBuilder.getStartInstance();
builder.newRow();
builder.field(RemotePanel.FIELD_ANSWER_CODE, RemotePanel.CODE_SUCCESS);
builder.field(RemotePanel.FIELD_URL, url);
sendReply(req,resp,callback,builder);
}
protected void replyLoad(String bookKey,String versionKey,HttpServletRequest request, HttpServletResponse resp) throws IOException {
String callback = extractCallback(request);
if (callback==null) {
//no callback, just print it
printCallbackError(resp);
return;
}
JSONBuilder builder = JSONBuilder.getStartInstance();
builder.newRow();
builder.field(RemotePanel.FIELD_ANSWER_CODE, RemotePanel.CODE_LOAD);
String req = request.getRequestURL().toString();
StringBuffer url = new StringBuffer(req.substring(0,req.lastIndexOf("/")));
url.append("/loadModel.js?");
if (versionKey==null) {
url.append(LoadModelServlet.FIELD_BOOK_ID);
url.append('=');
url.append(bookKey);
} else {
url.append(LoadModelServlet.FIELD_BOOK_VERSION_ID);
url.append('=');
url.append(versionKey);
}
builder.field(RemotePanel.FIELD_URL, url.toString());
sendReply(request,resp,callback,builder);
}
protected ModelPersist getModel(String mod, HttpServletRequest req, HttpServletResponse resp,AppConstants appConstants,AppMessages appMessages) throws LogicException {
Document result;
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setValidating(false);
dbf.setNamespaceAware(false);
DocumentBuilder db = dbf.newDocumentBuilder();
InputSource inputSource = new InputSource(new StringReader(mod));
result = db.parse(inputSource);
} catch (Exception e) {
throw new LogicException(e);
}
ModelPersist model = new ModelPersist(appConstants,appMessages);
XMLModelParser parser = new XMLModelParser();
try {
model.restore(result, parser);
} catch (Throwable e) {
throw new LogicException(e);
}
return model;
}
protected ModelPersist getModelFromRequest(PersistenceManager em, JPAUser user, HttpServletRequest req, HttpServletResponse resp,AppConstants appConstants,AppMessages appMessages) throws LogicException {
if (user.getUpload()==null || user.getUpload().length()==0) {
throw new LogicException(appConstants.serverUploadModelBefore());
}
String id = req.getParameter(ServerExchangePanel.FIELD_DATA);
if (id==null) {
throw new LogicException(appConstants.serverNoBookID());
}
if (id.equals(user.getUploadExternalId())==false) {
throw new LogicException(appConstants.serverBookIDAndModelAreDifferent());
}
ModelPersist model = getModel(user.getUpload(),req, resp, appConstants, appMessages);
if (id.equals(model.getGameId())==false) {
throw new LogicException(appConstants.serverBookIDAndModelAreDifferent());
}
JPABook book = DAO.getBookDAO().findBook(em, user,model);
if (book != null && book.isLocked()) {
//this book is locked
throw new LogicException(appConstants.serverBookIsLocked());
}
return model;
}
}