001/* 002 * (C) Copyright 2006-2013 Nuxeo SAS (http://nuxeo.com/) and contributors. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * bstefanescu 016 * 017 * $Id$ 018 */ 019 020package org.nuxeo.ecm.mobile.webengine.document; 021 022import java.util.HashMap; 023import java.util.Map; 024 025import javax.servlet.http.HttpServletRequest; 026import javax.ws.rs.GET; 027import javax.ws.rs.Path; 028import javax.ws.rs.core.Response; 029 030import org.apache.commons.lang.StringUtils; 031import org.apache.commons.logging.Log; 032import org.apache.commons.logging.LogFactory; 033import org.nuxeo.ecm.automation.AutomationService; 034import org.nuxeo.ecm.automation.OperationContext; 035import org.nuxeo.ecm.automation.OperationException; 036import org.nuxeo.ecm.core.api.Blob; 037import org.nuxeo.ecm.core.api.DocumentModel; 038import org.nuxeo.ecm.core.api.DocumentRef; 039import org.nuxeo.ecm.core.api.NuxeoException; 040import org.nuxeo.ecm.core.api.NuxeoPrincipal; 041import org.nuxeo.ecm.core.api.blobholder.BlobHolder; 042import org.nuxeo.ecm.core.io.download.DownloadService; 043import org.nuxeo.ecm.core.rest.DocumentObject; 044import org.nuxeo.ecm.mobile.webengine.RedirectHelper; 045import org.nuxeo.ecm.mobile.webengine.adapter.JSonExportAdapter; 046import org.nuxeo.ecm.platform.preview.helper.PreviewHelper; 047import org.nuxeo.ecm.platform.url.api.DocumentViewCodecManager; 048import org.nuxeo.ecm.platform.usermanager.UserManager; 049import org.nuxeo.ecm.platform.web.common.vh.VirtualHostHelper; 050import org.nuxeo.ecm.webengine.WebException; 051import org.nuxeo.ecm.webengine.model.ResourceType; 052import org.nuxeo.ecm.webengine.model.WebContext; 053import org.nuxeo.runtime.api.Framework; 054 055import static org.nuxeo.ecm.mobile.filter.ApplicationRedirectionFilter.INITIAL_TARGET_URL_PARAM_NAME; 056 057/** 058 * This Class resolve a DocumentModel and expose differents restitutions according Adapter defined (PreviewAdapter, 059 * CommentAdapter) in uri and "mode" parameter given as parameter into the url. Default mode if given doesn't exist or 060 * not set is view mode. 061 * 062 * @author <a href="mailto:bjalon@nuxeo.com">Benjamin JALON</a> 063 * @since 5.5 064 */ 065public class MobileDocument extends DocumentObject { 066 067 private static final Log log = LogFactory.getLog(MobileDocument.class); 068 069 public MobileDocument(WebContext ctx, DocumentRef docRef) { 070 try { 071 ResourceType resType = ctx.getModule().getType("Document"); 072 DocumentModel docModel = ctx.getCoreSession().getDocument(docRef); 073 initialize(ctx, resType, docModel); 074 ctx.push(this); 075 } catch (NuxeoException e) { 076 throw WebException.wrap(e); 077 } 078 } 079 080 /** 081 * Needed to not break the navigation after a false PUT see NXP-8778 as I'm redirected to this /@put URL 082 */ 083 @GET 084 @Path("@put") 085 public Object redirectToRealURL() { 086 String uri = ctx.getRequest().getRequestURI(); 087 // Remove the @put 088 uri = uri.substring(0, uri.length() - "@put".length() - 1); 089 String queryString = ctx.getRequest().getQueryString(); 090 return redirect(uri + (queryString != null ? "?" + queryString : "")); 091 } 092 093 @GET 094 @Path("mailIt") 095 public Object emailToCurrentPrincipal() { 096 try { 097 OperationContext subctx = new OperationContext(ctx.getCoreSession(), null); 098 subctx.setInput(getDocument()); 099 getAutomationService().run(subctx, "sendEmailToMe"); 100 } catch (NuxeoException | OperationException e) { 101 log.error(e, e); 102 return Response.status(400).build(); 103 } 104 return Response.ok().build(); 105 } 106 107 @Path("like") 108 public Object doLike() { 109 try { 110 return ctx.newObject("Like", getDocument()); 111 } catch (NuxeoException e) { 112 log.debug(e, e); 113 return ctx.newObject("Empty"); 114 } 115 } 116 117 @Path("hasLiked") 118 public Object doHasLiked() { 119 try { 120 return ctx.newObject("hasLiked", getDocument()); 121 } catch (NuxeoException e) { 122 log.debug(e, e); 123 return ctx.newObject("Empty"); 124 } 125 } 126 127 @Override 128 public Object doGet() { 129 Map<String, Object> args = new HashMap<String, Object>(); 130 131 // must override the original doGet to override the resolution 132 // so get parameter into the request instead injection 133 HttpServletRequest request = ctx.getRequest(); 134 String mode = request.getParameter("mode"); 135 if (mode == null) { 136 mode = "view"; 137 } 138 139 // if url from JSF => ask to push mobile URL into browser history 140 if (request.getParameter(INITIAL_TARGET_URL_PARAM_NAME) != null) { 141 String mobileURL = String.format("%s/doc/%s?mode=%s", ctx.getRoot().getPath(), doc.getId(), mode); 142 args.put("mobileURL", mobileURL); 143 } 144 args.put("hasBlob", getHasBlob()); 145 146 // Add the JSON DForm export 147 JSonExportAdapter json = (JSonExportAdapter) ctx.newObject("JSONExport"); 148 args.put("doc", json.doGet(request.getRequestURI(), "post")); 149 150 return getView(mode).args(args); 151 } 152 153 protected boolean getHasBlob() { 154 DocumentModel doc = getDocument(); 155 BlobHolder bh = doc.getAdapter(BlobHolder.class); 156 return bh != null && bh.getBlob() != null; 157 } 158 159 public boolean hasPreview() { 160 if (doc.hasSchema("file") && doc.getPropertyValue("file:content") != null) { 161 return PreviewHelper.typeSupportsPreview(doc); 162 } 163 return false; 164 } 165 166 public NuxeoPrincipal getPrincipal() { 167 if (ctx.getPrincipal() instanceof NuxeoPrincipal) { 168 return (NuxeoPrincipal) ctx.getPrincipal(); 169 } 170 171 throw new WebException("Principal found is not a NuxeoPrincipal can't generate it!"); 172 } 173 174 public String getJSFURLPath(DocumentModel docModel) { 175 return RedirectHelper.getJSFDocumentPath(docModel, VirtualHostHelper.getBaseURL(ctx.getRequest())); 176 } 177 178 public String getDownloadURL() { 179 DocumentModel docModel = getDocument(); 180 181 return getDownloadURL(docModel); 182 } 183 184 public String getDownloadURL(DocumentModel docModel) { 185 Blob blob = doc.getAdapter(BlobHolder.class).getBlob(); 186 DownloadService downloadService = Framework.getService(DownloadService.class); 187 String xpath = DownloadService.BLOBHOLDER_0; 188 String filename = blob.getFilename(); 189 return getNuxeoContextPath() + "/" + downloadService.getDownloadUrl(doc, xpath, filename) + "?mimetype=" 190 + blob.getMimeType(); 191 } 192 193 public String getJSFURLPath() { 194 return getJSFURLPath(getDocument()); 195 } 196 197 // **** TODO REMOVE WHEN PREVIEW WITH NAVIGATION RESOLVED **** 198 private String nuxeoContextPath; 199 200 private DocumentViewCodecManager codecManager; 201 202 public String getPreviewURL() { 203 Object targetObject = ctx.getTargetObject(); 204 if (!(targetObject instanceof MobileDocument)) { 205 throw new WebException("Target Object must be MobileDocument"); 206 } 207 return getNuxeoContextPath() + "/" + PreviewHelper.getPreviewURL(((MobileDocument) targetObject).getDocument()); 208 } 209 210 private String getNuxeoContextPath() { 211 if (nuxeoContextPath == null) { 212 nuxeoContextPath = Framework.getProperty("org.nuxeo.ecm.contextPath"); 213 } 214 return nuxeoContextPath; 215 } 216 217 private AutomationService getAutomationService() { 218 return Framework.getService(AutomationService.class); 219 } 220 221 public String getDisplayPrincipalName(String name) { 222 NuxeoPrincipal principal = Framework.getService(UserManager.class).getPrincipal(name); 223 if (principal != null) { 224 return getDisplayPrincipalName(principal); 225 } 226 return name; 227 } 228 229 /** 230 * Return the display name of an expected principal. It passes as an Object to prevent Freemarker to thrown an 231 * exception when creator is null. 232 * 233 * @param object must be of type org.nuxeo.ecm.core.api.NuxeoPrincipal 234 * @return the display name will be empty if not a NuxeoPrincipal 235 */ 236 public String getDisplayPrincipalName(Object object) { 237 if (object instanceof NuxeoPrincipal) { 238 NuxeoPrincipal principal = (NuxeoPrincipal) object; 239 String display = (principal.getFirstName() + " " + principal.getLastName()).trim(); 240 return StringUtils.isBlank(display) ? principal.getName() : display; 241 } 242 return ""; 243 } 244 245 public String getDisplayPrincipalName() { 246 return getDisplayPrincipalName(getPrincipal()); 247 } 248 249}