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