package com.iambookmaster.server; import java.io.IOException; import java.io.PrintWriter; import java.io.StringReader; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import javax.jdo.PersistenceManager; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Document; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import com.google.appengine.api.datastore.Key; import com.google.appengine.api.datastore.KeyFactory; import com.google.appengine.api.users.UserService; import com.google.appengine.api.users.UserServiceFactory; import com.iambookmaster.client.ServerExchangePanel; import com.iambookmaster.client.beans.ObjectBean; import com.iambookmaster.client.beans.Paragraph; import com.iambookmaster.client.beans.ParagraphConnection; import com.iambookmaster.client.common.JSONBuilder; import com.iambookmaster.client.editor.ModelPersist; import com.iambookmaster.client.exceptions.JSONException; import com.iambookmaster.client.locale.AppConstants; import com.iambookmaster.client.locale.AppMessages; import com.iambookmaster.client.model.Model; import com.iambookmaster.client.paragraph.BookCreator; import com.iambookmaster.client.paragraph.BookCreatorListener; import com.iambookmaster.client.paragraph.BookDecorator; import com.iambookmaster.server.beans.JPABook; import com.iambookmaster.server.beans.JPABookVersion; import com.iambookmaster.server.beans.JPAClob; import com.iambookmaster.server.beans.JPAUser; import com.iambookmaster.server.dao.BooksDAO; import com.iambookmaster.server.dao.DAO; import com.iambookmaster.server.logic.QSPBookDecrator; import com.iambookmaster.server.logic.URQBookDecrator; import com.iambookmaster.server.tags.LoadModelTag; public class LoadModelServlet extends AbstractServlet { private static final long serialVersionUID = 1L; private static final Logger log = Logger.getLogger(LoadModelServlet.class.getName()); public static final String FIELD_BOOK_ID = "b"; public static final String FIELD_BOOK_VERSION_ID = "v"; public static final String FIELD_TYPE = "t"; public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { UserService userService = UserServiceFactory.getUserService(); AppConstants appConstants = LocalMessages.getInstance(AppConstants.class, LocalMessages.getLocale(req,resp)); AppMessages appMessages = LocalMessages.getInstance(AppMessages.class, LocalMessages.getLocale(req,resp)); if (userService.isUserLoggedIn()==false) { sendReplay(resp,ServerExchangePanel.ERROR_NO_LOGIN,appConstants.serverNotLoggedIn()); return; } PersistenceManager em = getPM(req); JPABook book; JPABookVersion version; String type=req.getParameter(FIELD_TYPE); Object result = getBookOrVersionAndValidate(type,em,userService,req,resp,appConstants); if (result instanceof JPABook) { book = (JPABook) result; version = null; } else if (result instanceof JPABookVersion) { version = (JPABookVersion) result; book = null; } else { //error return; } BooksDAO booksDAO = DAO.getBookDAO(); if (type==null || LoadModelTag.TYPE_EDITOR.equals(type)) { //Model for editor sendModelToEditor(book,version,req,resp,appConstants,appMessages); } else if (LoadModelTag.TYPE_HTML.equals(type)) { sendModelToHTML(book,version,req,resp); } else if (LoadModelTag.TYPE_TXT.equals(type)) { String data; if (version== null) { data = booksDAO.getCLOB(em, book, JPAClob.TYPE_TEXT); } else { data = booksDAO.getCLOB(em, version, JPAClob.TYPE_TEXT); } sendModelToFile(data,req,resp,Translit.toTranslit(book.getName().replace(' ', '_'))+".txt","UTF-8"); } else if (LoadModelTag.TYPE_URQ.equals(type)) { try { ModelPersist model = loadModel(resp,em,book,version,booksDAO,appConstants,appMessages); BookDecorator decorator = new URQBookDecrator(model,appConstants,appMessages); sendModelToFile(model,decorator,req,resp,Translit.toTranslit(book.getName().replace(' ', '_'))+".qst",URQBookDecrator.ENCODING,appConstants,appMessages); } catch (Exception e) { e.printStackTrace(); log.log(Level.SEVERE,e.getMessage(),e); resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage()); } } else if (LoadModelTag.TYPE_URQ_SHORT.equals(type)) { try { ModelPersist model = loadModel(resp,em,book,version,booksDAO,appConstants,appMessages); model.getSettings().setDisableAudio(true); model.getSettings().setDisableImages(true); BookDecorator decorator = new URQBookDecrator(model,appConstants,appMessages); sendModelToFile(model,decorator,req,resp,Translit.toTranslit(book.getName().replace(' ', '_'))+".qst",URQBookDecrator.ENCODING,appConstants,appMessages); } catch (Exception e) { e.printStackTrace(); log.log(Level.SEVERE,e.getMessage(),e); resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage()); } } else if (LoadModelTag.TYPE_QSP.equals(type)) { try { ModelPersist model = loadModel(resp,em,book,version,booksDAO,appConstants,appMessages); BookDecorator decorator = new QSPBookDecrator(model,appConstants,appMessages); sendModelToFile(model,decorator,req,resp,Translit.toTranslit(book.getName().replace(' ', '_'))+".qsp",QSPBookDecrator.ENCODING,appConstants,appMessages); } catch (Exception e) { e.printStackTrace(); log.log(Level.SEVERE,e.getMessage(),e); resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage()); } } else if (LoadModelTag.TYPE_PROJECT.equals(type)) { sendModelToProject(em,book,version,req,resp); } } private void sendModelToFile(Model model,BookDecorator decorator, HttpServletRequest req, HttpServletResponse resp, String fileName, String encoding,final AppConstants constants,final AppMessages messages) throws IOException { BookCreator creator = new BookCreator(model); List<Paragraph> list = model.getParagraphs(); Paragraph[] book = new Paragraph[list.size()]; for (Paragraph paragraph : list) { // assertNotSame(paragraph.getNumber(),0); // assertNull(book[paragraph.getNumber()-1]); book[paragraph.getNumber()-1]=paragraph; } creator.createText(book, new BookCreatorListener(){ public void algorithmError(int code) { fail(messages.validatorAlgorithmError(code)); } private void fail(String error) { // TODO Auto-generated method stub } public void allIterationsFailed() { } public boolean checkTimiout() { return false; } public void iterationFailed(int fail, int total) { } public void noSupported() { fail("noSupported"); } public void numberNotSet(ObjectBean objectBean) { fail(messages.validationObjectDoesNotHaveSecretKey(objectBean.getName())); } public void numberNotSet(Paragraph paragraph) { fail(messages.validationParagraphNumberNotSet(paragraph.getName())); } public void numberTooLarge(Paragraph paragraph, int max) { fail(messages.validationParagraphNumberOutOfRange(paragraph.getName(),max)); } public void numbersDuplicated(Paragraph paragraph,Paragraph paragraph2) { fail(messages.validationParagraphNameDuplicated(paragraph.getName(),paragraph.getNumber(),paragraph2.getName())); } public void tooManyObjects() { fail("tooManyObjects"); } public void wrongObjectSecretKey(ParagraphConnection connection) { fail(messages.validationObjectHasWrongSecretKey(connection.getObject().getName(),connection.getObject().getKey(), connection.getFrom().getNumber(),connection.getFrom().getName(), connection.getTo().getNumber(),connection.getTo().getName())); } }, decorator); String module = decorator.toString(); sendModelToFile(module,req,resp,fileName,encoding); } private ModelPersist loadModel(HttpServletResponse resp,PersistenceManager em, JPABook book, JPABookVersion version, BooksDAO booksDAO, AppConstants appConstants,AppMessages appMessages) throws JSONException, ParserConfigurationException, SAXException, IOException { String data; if (version== null) { data = booksDAO.getCLOB(em, book, JPAClob.TYPE_MODEL); } else { data = booksDAO.getCLOB(em, version, JPAClob.TYPE_MODEL); } Document result; DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setValidating(false); dbf.setNamespaceAware(false); DocumentBuilder db = dbf.newDocumentBuilder(); InputSource inputSource = new InputSource(new StringReader(data)); result = db.parse(inputSource); ModelPersist model = new ModelPersist(appConstants,appMessages); XMLModelParser parser = new XMLModelParser(); model.restore(result, parser); return model; } protected Object getBookOrVersionAndValidate(String type, PersistenceManager em, UserService userService, HttpServletRequest req, HttpServletResponse resp, AppConstants appConstants) throws IOException{ String bookId = req.getParameter(FIELD_BOOK_ID); BooksDAO booksDAO = DAO.getBookDAO(); JPABook book; JPABookVersion version; if (bookId==null) { String bookVersionId = req.getParameter(FIELD_BOOK_VERSION_ID); Key bookVersionKey=null; if (bookVersionId == null) { sendError(type,resp,ServerExchangePanel.ERROR_NO_BOOK_ID,appConstants.serverNoBookID()); return null; } try { bookVersionKey = KeyFactory.stringToKey(bookVersionId); } catch (Exception e) { sendError(type,resp,ServerExchangePanel.ERROR_INVALID_BOOK_VERSION_ID,appConstants.serverInvalidBookVersionID()); return null; } version = booksDAO.findBookVersion(em,bookVersionKey); if (version==null) { sendError(type,resp,ServerExchangePanel.ERROR_BOOK_VERSION_NOT_FOUND,appConstants.serverUnknownBookVersion()); return null; } book = booksDAO.findBook(em, version.getBook()); } else { version = null; Key bookKey; try { bookKey = KeyFactory.stringToKey(bookId); } catch (Exception e) { sendError(type,resp,ServerExchangePanel.ERROR_INVALID_BOOK_ID,appConstants.serverInvalidBookID()); return null; } book = booksDAO.findBook(em, bookKey); if (book==null) { sendError(type,resp,ServerExchangePanel.ERROR_BOOK_NOT_FOUND,appConstants.serverBookNotFound()); return null; } } if (userService.isUserAdmin()==false) { //administrator can load anything, other - owner only JPAUser user = DAO.getUsersDAO().findOrCreateUser(em, userService.getCurrentUser()); if (user.getId().equals(book.getOwner())==false) { sendError(type,resp,ServerExchangePanel.ERROR_NOT_OWNER,appConstants.serverNotOwnerOfBook()); return null; } } if (book==null) { return version; } else { return book; } } protected void sendError(String type,HttpServletResponse resp, int code, String message) throws IOException { if (type==null || LoadModelTag.TYPE_EDITOR.equals(type)) { sendReplay(resp, code, message); } else { resp.sendError(HttpServletResponse.SC_BAD_REQUEST, message); } } private void sendModelToProject(PersistenceManager em, JPABook book, JPABookVersion version, HttpServletRequest req, HttpServletResponse resp) throws IOException { String data; BooksDAO booksDAO = DAO.getBookDAO(); if (version== null) { data = booksDAO.getCLOB(em, book, JPAClob.TYPE_MODEL); } else { data = booksDAO.getCLOB(em, version, JPAClob.TYPE_MODEL); } Document result; try { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setValidating(false); dbf.setNamespaceAware(false); DocumentBuilder db = dbf.newDocumentBuilder(); InputSource inputSource = new InputSource(new StringReader(data)); result = db.parse(inputSource); } catch (Exception e) { log.log(Level.SEVERE,e.getMessage(),e); resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,e.getMessage()); return; } ModelPersist model = new ModelPersist(LocalMessages.getInstance(AppConstants.class, LocalMessages.getLocale(req,resp)),LocalMessages.getInstance(AppMessages.class, LocalMessages.getLocale(req,resp))); XMLModelParser parser = new XMLModelParser(); try { model.restore(result, parser); } catch (Throwable e) { log.log(Level.SEVERE,e.getMessage(),e); resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,e.getMessage()); return; } JSONBuilder builder = JSONBuilder.getStartInstance(); model.toJSON(Model.EXPORT_ALL, builder); sendModelToFile(builder.toString(),req,resp,Translit.toTranslit(book.getName().replace(' ', '_'))+".txt","UTF-8"); } // private void sendModelToTXT(PersistenceManager em, JPABook book, JPABookVersion version, HttpServletRequest req, HttpServletResponse resp) throws IOException { // resp.setContentType("text/plain"); // resp.setCharacterEncoding("UTF-8"); // PrintWriter writer = resp.getWriter(); // String data; // BooksDAO booksDAO = DAO.getBookDAO(); // if (version== null) { // data = booksDAO.getCLOB(em, book, JPAClob.TYPE_MODEL); // } else { // data = booksDAO.getCLOB(em, version, JPAClob.TYPE_MODEL); // } // writer.append(data); // writer.flush(); // // } private void sendModelToFile(String content,HttpServletRequest req, HttpServletResponse resp, String fileName,String enconding) throws IOException { resp.setContentType("text/plain"); resp.setCharacterEncoding(enconding); resp.setHeader("Content-Disposition", "attachment;filename=" + fileName); PrintWriter writer = resp.getWriter(); writer.write(content); writer.flush(); writer.close(); } private void sendModelToHTML(JPABook book, JPABookVersion version, HttpServletRequest req, HttpServletResponse resp)throws IOException { resp.setContentType("text/html"); resp.setCharacterEncoding("UTF-8"); PrintWriter writer = resp.getWriter(); BooksDAO booksDAO = DAO.getBookDAO(); PersistenceManager em = getPM(req); if (version == null) { writer.append(booksDAO.getCLOB(em, book, JPAClob.TYPE_HTML)); } else { writer.append(booksDAO.getCLOB(em, version, JPAClob.TYPE_HTML)); } writer.flush(); } private void sendModelToEditor(JPABook book, JPABookVersion version, HttpServletRequest req, HttpServletResponse resp,AppConstants appConstants,AppMessages appMessages) throws IOException { String modelXML; BooksDAO booksDAO = DAO.getBookDAO(); PersistenceManager em = getPM(req); if (version == null) { modelXML = booksDAO.getCLOB(em, book, JPAClob.TYPE_MODEL); } else { modelXML = booksDAO.getCLOB(em, version, JPAClob.TYPE_MODEL); } Document result; try { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setValidating(false); dbf.setNamespaceAware(false); DocumentBuilder db = dbf.newDocumentBuilder(); InputSource inputSource = new InputSource(new StringReader(modelXML)); result = db.parse(inputSource); } catch (Exception e) { log.log(Level.SEVERE,e.getMessage(),e); resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,e.getMessage()); // sendReplay(resp,ServerExchangePanel.ERROR_INVALID_MODEL,e.getMessage()); return; } ModelPersist model = new ModelPersist(appConstants,appMessages); XMLModelParser parser = new XMLModelParser(); try { model.restore(result, parser); } catch (Throwable e) { log.log(Level.SEVERE,e.getMessage(),e); resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,e.getMessage()); // sendReplay(resp,ServerExchangePanel.ERROR_INVALID_MODEL,e.getMessage()); return; } JSONBuilder builder = JSONBuilder.getStartInstance(); model.toJSON(Model.EXPORT_ALL, builder); sendReplay(resp,ServerExchangePanel.LOAD_OK,"loaded",builder.toString()); } private void sendReplay(HttpServletResponse resp, int code, String message) { sendReplay(resp,code,message,null); } private void sendReplay(HttpServletResponse resp, int code, String message, String data) { try { // content-type: resp.setContentType("application/x-javascript"); resp.setCharacterEncoding("UTF-8"); PrintWriter writer = resp.getWriter(); writer.write("//Loading model of Game-Book\n"); writer.write("var result = {};\nresult."); if (data != null) { writer.write(ServerExchangePanel.FIELD_DATA); writer.write('='); writer.write(data); writer.write(";\n"); } if (message != null) { writer.write("result."); writer.write(ServerExchangePanel.FIELD_MESSAGE); writer.write("='"); writer.write(message); writer.write("';\n"); } writer.write("result."); writer.write(ServerExchangePanel.FIELD_CODE); writer.write('='); writer.write(String.valueOf(code)); writer.write(";\ndocument.iambookmasterLoad(result);\n"); resp.flushBuffer(); } catch (IOException e) { log.log(Level.WARNING,e.getMessage()); } } }