Java tutorial
/* * Copyright (C) 2018 Sonicle S.r.l. * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU Affero General Public License version 3 as published by * the Free Software Foundation with the addition of the following permission * added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED * WORK IN WHICH THE COPYRIGHT IS OWNED BY SONICLE, SONICLE DISCLAIMS THE * WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more * details. * * You should have received a copy of the GNU Affero General Public License * along with this program; if not, see http://www.gnu.org/licenses or write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA. * * You can contact Sonicle S.r.l. at email address sonicle[at]sonicle[dot]com * * The interactive user interfaces in modified source and object code versions * of this program must display Appropriate Legal Notices, as required under * Section 5 of the GNU Affero General Public License version 3. * * In accordance with Section 7(b) of the GNU Affero General Public License * version 3, these Appropriate Legal Notices must retain the display of the * Sonicle logo and Sonicle copyright notice. If the display of the logo is not * reasonably feasible for technical reasons, the Appropriate Legal Notices must * display the words "Copyright (C) 2018 Sonicle S.r.l.". */ package com.sonicle.webtop.core.app.servlet; import com.sonicle.commons.URIUtils; import com.sonicle.commons.http.HttpClientUtils; import com.sonicle.commons.web.ServletUtils; import com.sonicle.commons.web.json.MapItem; import com.sonicle.commons.web.json.Payload; import com.sonicle.webtop.core.app.sdk.BaseDocEditorDocumentHandler; import com.sonicle.webtop.core.app.AbstractServlet; import com.sonicle.webtop.core.app.DocEditorManager; import com.sonicle.webtop.core.app.WT; import com.sonicle.webtop.core.app.WebTopApp; import com.sonicle.webtop.core.app.sdk.WTServletException; import com.sonicle.webtop.core.app.servlet.js.DocEditorCallbackPayload; import com.sonicle.webtop.core.app.servlet.js.DocEditorCallbackResponse; import com.sonicle.webtop.core.sdk.DomainURIPath; import java.io.IOException; import java.io.InputStream; import java.net.URI; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.apache.http.client.HttpClient; import org.apache.shiro.subject.support.SubjectThreadState; import org.apache.shiro.util.ThreadState; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * * @author malbinola */ public class DocEditor extends AbstractServlet { private static final Logger logger = LoggerFactory.getLogger(DocEditor.class); public static final String URL = "/doc-editor"; // Shiro.ini must reflect this URI! public static final String DOWNLOAD_PATH = "/oo/download"; public static final String TRACK_PATH = "/oo/track"; public static final String SESSION_ID_PARAM = "sid"; public static final String EDITING_ID_PARAM = "eid"; @Override protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { WebTopApp wta = WebTopApp.get(request); ThreadState threadState = new SubjectThreadState(wta.getAdminSubject()); threadState.bind(); try { processRequestAsAdmin(request, response); } catch (Throwable t) { logger.error("Error fulfilling request", t); throw t; } finally { threadState.clear(); } } protected void processRequestAsAdmin(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { DomainURIPath path = new DomainURIPath(URIUtils.removeTrailingSeparator(request.getPathInfo())); WebTopApp wta = WebTopApp.get(request); DocEditorManager docEdMgr = wta.getDocEditorManager(); String domainId = WT.findDomainIdByPublicName(path.getDomainPublicName()); if (domainId == null) throw new WTServletException("Invalid domain public name [{0}]", path.getDomainPublicName()); if (!wta.getDocumentServerEnabled(domainId)) throw new WTServletException("DocumentServer not enabled for domain [{}]", domainId); String remainingPath = path.getRemainingPath(); if (StringUtils.equalsIgnoreCase(remainingPath, DOWNLOAD_PATH)) { String editingId = ServletUtils.getStringParameter(request, EDITING_ID_PARAM, true); BaseDocEditorDocumentHandler docHandler = docEdMgr.getDocumentHandler(editingId); if (docHandler == null) throw new WTServletException("Missing DocumentHandler [{}]", editingId); ServletUtils.setContentTypeHeader(response, "application/octet-stream"); IOUtils.copy(docHandler.readDocument(), response.getOutputStream()); } else if (StringUtils.equalsIgnoreCase(remainingPath, TRACK_PATH)) { String editingId = ServletUtils.getStringParameter(request, EDITING_ID_PARAM, true); Payload<MapItem, DocEditorCallbackPayload> payload = ServletUtils.getPayload(request, DocEditorCallbackPayload.class); if (payload.data.status == 1) { logger.debug("Document is being edited [{}, {}]", editingId, payload.data.key); ServletUtils.writeJsonResponse(response, new DocEditorCallbackResponse(0)); } else if ((payload.data.status == 2) || (payload.data.status == 6)) { BaseDocEditorDocumentHandler docHandler = docEdMgr.getDocumentHandler(editingId); if (docHandler == null) throw new WTServletException("Missing DocumentHandler [{}]", editingId); if (payload.data.status == 2) { logger.debug("Document is ready for saving [{}, {}]", editingId, payload.data.key); } else if (payload.data.status == 6) { logger.debug("Document is being edited, but the current document state is saved [{}, {}]", editingId, payload.data.key); } if (!docHandler.isWriteSupported()) throw new WTServletException("Write is not supported here [{}]", editingId); URI url = URIUtils.createURIQuietly(payload.data.url); if (url == null) throw new WTServletException("Invalid URL [{}]", payload.data.url); /* if (true) { long lastModified = docHandler.getLastModifiedTime(); if (lastModified != -1) { String key = docEdMgr.buildDocumentKey(docHandler.getDocumentUniqueId(), lastModified); if (!StringUtils.equals(payload.data.key, key)) { throw new WTServletException("Original file was modified outside this session [{}]", editingId); } } } */ InputStream is = null; try { HttpClient httpCli = HttpClientUtils .createBasicHttpClient(HttpClientUtils.configureSSLAcceptAll(), url); is = HttpClientUtils.getContent(httpCli, url); docHandler.writeDocument(is); } catch (IOException ex) { throw new WTServletException("Unable to save edited content [{}]", editingId, ex); } finally { IOUtils.closeQuietly(is); } //UserProfileId profileId = new UserProfileId(payload.data.users.get(0)); if (payload.data.status == 2) { docEdMgr.unregisterDocumentHandler(editingId); } ServletUtils.writeJsonResponse(response, new DocEditorCallbackResponse(0)); } else if ((payload.data.status == 3) || (payload.data.status == 7)) { if (payload.data.status == 3) { logger.error("Document saving error has occurred [{}, {}]", editingId, payload.data.key); logger.error("Changes URL: {}", payload.data.changesurl); } else if (payload.data.status == 7) { logger.error("Error has occurred while force saving the document [{}, {}]", editingId, payload.data.key); } docEdMgr.unregisterDocumentHandler(editingId); ServletUtils.writeJsonResponse(response, new DocEditorCallbackResponse(0)); } else if (payload.data.status == 4) { logger.debug("Document is closed with no changes [{}, {}]", editingId, payload.data.key); docEdMgr.unregisterDocumentHandler(editingId); ServletUtils.writeJsonResponse(response, new DocEditorCallbackResponse(0)); } } } }