001package org.nuxeo.ecm.webapp.action; 002 003import static org.jboss.seam.ScopeType.CONVERSATION; 004import static org.nuxeo.ecm.webapp.helpers.EventNames.NAVIGATE_TO_DOCUMENT; 005 006import java.io.Serializable; 007import java.util.HashMap; 008import java.util.Map; 009 010import javax.faces.context.FacesContext; 011import javax.servlet.ServletRequest; 012import javax.servlet.http.HttpServletRequest; 013 014import org.jboss.seam.annotations.In; 015import org.jboss.seam.annotations.Install; 016import org.jboss.seam.annotations.Name; 017import org.jboss.seam.annotations.Observer; 018import org.jboss.seam.annotations.Scope; 019import org.nuxeo.ecm.core.api.CoreSession; 020import org.nuxeo.ecm.core.api.DocumentModel; 021import org.nuxeo.ecm.core.api.PathRef; 022import org.nuxeo.ecm.core.api.repository.RepositoryManager; 023import org.nuxeo.ecm.core.api.security.SecurityConstants; 024import org.nuxeo.ecm.platform.actions.Action; 025import org.nuxeo.ecm.platform.actions.ejb.ActionManager; 026import org.nuxeo.ecm.platform.types.adapter.TypeInfo; 027import org.nuxeo.ecm.platform.ui.web.api.NavigationContext; 028import org.nuxeo.ecm.platform.ui.web.api.WebActions; 029import org.nuxeo.ecm.platform.ui.web.rest.api.URLPolicyService; 030import org.nuxeo.ecm.platform.url.api.DocumentView; 031import org.nuxeo.runtime.api.Framework; 032 033/** 034 * Handle Main tab related actions. 035 * <p> 036 * Maintains a Map of tab id -> contextual document. 037 * 038 * @author <a href="mailto:troger@nuxeo.com">Thomas Roger</a> 039 * @since 5.4.2 040 */ 041@Name("mainTabsActions") 042@Scope(CONVERSATION) 043@Install(precedence = Install.FRAMEWORK) 044public class MainTabsActions implements Serializable { 045 046 private static final long serialVersionUID = 1L; 047 048 /** 049 * @deprecated since 5.5, use {@link WebActions#MAIN_TABS_CATEGORY} instead 050 */ 051 @Deprecated 052 public static final String MAIN_TABS_CATEGORY = WebActions.MAIN_TABS_CATEGORY; 053 054 /** 055 * @deprecated since 5.5, use {@link WebActions#DOCUMENTS_MAIN_TAB_ID} instead 056 */ 057 @Deprecated 058 public static final String DOCUMENT_MANAGEMENT_ACTION = WebActions.DOCUMENTS_MAIN_TAB_ID; 059 060 /** 061 * @deprecated since 5.5, use {@link WebActions#TAB_IDS_PARAMETER} instead 062 */ 063 @Deprecated 064 public static final String TAB_IDS_PARAMETER = WebActions.TAB_IDS_PARAMETER; 065 066 /** 067 * @deprecated since 5.5, use {@link WebActions#MAIN_TAB_ID_PARAMETER} instead 068 */ 069 @Deprecated 070 public static final String MAIN_TAB_ID_PARAMETER = WebActions.MAIN_TAB_ID_PARAMETER; 071 072 public static final String DEFAULT_VIEW = "view_documents"; 073 074 @In(create = true) 075 protected transient RepositoryManager repositoryManager; 076 077 @In(create = true, required = false) 078 protected transient CoreSession documentManager; 079 080 @In(create = true, required = false) 081 protected transient NavigationContext navigationContext; 082 083 @In(create = true) 084 protected transient WebActions webActions; 085 086 @In(create = true, required = false) 087 protected transient ActionManager actionManager; 088 089 protected Map<String, DocumentModel> documentsByMainTabs = new HashMap<String, DocumentModel>(); 090 091 @Observer({ NAVIGATE_TO_DOCUMENT }) 092 public void updateContextualDocument() { 093 if (!shouldHandleRequest()) { 094 return; 095 } 096 String currentMainTab = getCurrentMainTabFromRequest(); 097 if (currentMainTab == null) { 098 currentMainTab = webActions.getCurrentTabId(WebActions.MAIN_TABS_CATEGORY); 099 } 100 DocumentModel currentDocument = navigationContext.getCurrentDocument(); 101 documentsByMainTabs.put(currentMainTab, currentDocument); 102 } 103 104 /** 105 * Only handle non POST requests 106 */ 107 protected boolean shouldHandleRequest() { 108 ServletRequest request = (ServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest(); 109 if (request instanceof HttpServletRequest) { 110 HttpServletRequest httpServletRequest = (HttpServletRequest) request; 111 return !httpServletRequest.getMethod().equalsIgnoreCase("post"); 112 } 113 return false; 114 } 115 116 protected String getCurrentMainTabFromRequest() { 117 URLPolicyService service = Framework.getService(URLPolicyService.class); 118 ServletRequest request = (ServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest(); 119 if (request instanceof HttpServletRequest) { 120 DocumentView docView = service.getDocumentViewFromRequest((HttpServletRequest) request); 121 if (docView == null) { 122 return null; 123 } 124 String tabIds = docView.getParameter(WebActions.TAB_IDS_PARAMETER); 125 String mainTabId = docView.getParameter(WebActions.MAIN_TAB_ID_PARAMETER); 126 if (mainTabId != null && !mainTabId.isEmpty()) { 127 tabIds = mainTabId; 128 } 129 if (tabIds != null && tabIds.contains(WebActions.MAIN_TABS_CATEGORY)) { 130 String[] encodedActions = tabIds.split(","); 131 for (String encodedAction : encodedActions) { 132 if (encodedAction.startsWith(WebActions.MAIN_TABS_CATEGORY)) { 133 String[] actionInfo = encodedAction.split(":"); 134 if (actionInfo != null && actionInfo.length > 1) { 135 return actionInfo[1]; 136 } 137 } 138 } 139 } 140 } 141 return null; 142 } 143 144 /** 145 * Set the document used for a given {@code mainTabId}. 146 * 147 * @since 5.7 148 */ 149 public void setDocumentFor(String mainTabId, DocumentModel doc) { 150 documentsByMainTabs.put(mainTabId, doc); 151 } 152 153 public DocumentModel getDocumentFor(String mainTabId) { 154 return getDocumentFor(mainTabId, navigationContext.getCurrentDocument()); 155 } 156 157 public DocumentModel getDocumentFor(String mainTabId, DocumentModel defaultDocument) { 158 DocumentModel doc = documentsByMainTabs.get(mainTabId); 159 if (doc == null || !documentManager.exists(doc.getRef()) 160 || !documentManager.hasPermission(doc.getRef(), SecurityConstants.READ)) { 161 documentsByMainTabs.put(mainTabId, defaultDocument); 162 doc = null; 163 } 164 165 if (doc != null && !documentManager.exists(new PathRef(doc.getPathAsString()))) { 166 // path has changed, refresh the document to have a correct URL 167 doc = documentManager.getDocument(doc.getRef()); 168 documentsByMainTabs.put(mainTabId, doc); 169 } 170 171 return doc != null ? doc : defaultDocument; 172 } 173 174 public String getViewFor(Action mainTabAction) { 175 if (!mainTabAction.getId().equals(WebActions.DOCUMENTS_MAIN_TAB_ID)) { 176 return mainTabAction.getLink(); 177 } 178 179 DocumentModel doc = getDocumentFor(mainTabAction.getId(), navigationContext.getCurrentDocument()); 180 if (doc != null) { 181 TypeInfo typeInfo = doc.getAdapter(TypeInfo.class); 182 return typeInfo.getDefaultView(); 183 } 184 return DEFAULT_VIEW; 185 } 186 187 public String getViewFor(String mainTabId) { 188 Action mainTabAction = actionManager.getAction(mainTabId); 189 return mainTabAction != null ? getViewFor(mainTabAction) : null; 190 } 191 192 public String getPatternFor(String mainTabId) { 193 URLPolicyService service = Framework.getService(URLPolicyService.class); 194 // FIXME: find some way to reference the pattern in the action, 195 // assume the pattern will be the same than the default one for 196 // now, or use the default one. 197 if (!WebActions.DOCUMENTS_MAIN_TAB_ID.equals(mainTabId) && service.hasPattern(mainTabId)) { 198 return mainTabId; 199 } 200 return service.getDefaultPatternName(); 201 } 202 203 public boolean isOnMainTab(String mainTabId) { 204 if (mainTabId != null && mainTabId.equals(webActions.getCurrentTabId(WebActions.MAIN_TABS_CATEGORY))) { 205 return true; 206 } 207 return false; 208 } 209 210}