/* * Copyright (C) 2003-2007 eXo Platform SAS. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License * as published by the Free Software Foundation; either version 3 * of the License, or (at your option) any later version. * * 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see<http://www.gnu.org/licenses/>. */ package org.exoplatform.ecm.webui.component.explorer; import org.apache.commons.lang.StringUtils; import org.exoplatform.ecm.jcr.model.Preference; import org.exoplatform.ecm.utils.text.Text; import org.exoplatform.ecm.webui.component.explorer.control.UIActionBar; import org.exoplatform.ecm.webui.component.explorer.control.UIAddressBar; import org.exoplatform.ecm.webui.component.explorer.control.UIControl; import org.exoplatform.ecm.webui.component.explorer.control.action.AddDocumentActionComponent; import org.exoplatform.ecm.webui.component.explorer.control.action.EditDocumentActionComponent; import org.exoplatform.ecm.webui.component.explorer.control.action.EditPropertyActionComponent; import org.exoplatform.ecm.webui.component.explorer.sidebar.UITreeExplorer; import org.exoplatform.ecm.webui.utils.JCRExceptionManager; import org.exoplatform.ecm.webui.utils.Utils; import org.exoplatform.portal.application.PortalRequestContext; import org.exoplatform.portal.webui.util.Util; import org.exoplatform.services.cms.documents.AutoVersionService; import org.exoplatform.services.cms.drives.DriveData; import org.exoplatform.services.cms.drives.ManageDriveService; import org.exoplatform.services.cms.drives.impl.ManageDriveServiceImpl; import org.exoplatform.services.cms.views.ManageViewService; import org.exoplatform.services.jcr.RepositoryService; import org.exoplatform.services.log.ExoLogger; import org.exoplatform.services.log.Log; import org.exoplatform.services.security.ConversationState; import org.exoplatform.services.wcm.utils.WCMCoreUtils; import org.exoplatform.web.application.ApplicationMessage; import org.exoplatform.webui.application.WebuiApplication; import org.exoplatform.webui.application.WebuiRequestContext; import org.exoplatform.webui.application.portlet.PortletRequestContext; import org.exoplatform.webui.config.annotation.ComponentConfig; import org.exoplatform.webui.core.UIApplication; import org.exoplatform.webui.core.UIPopupContainer; import org.exoplatform.webui.core.UIPortletApplication; import org.exoplatform.webui.core.UIRightClickPopupMenu; import org.exoplatform.webui.core.lifecycle.UIApplicationLifecycle; import org.exoplatform.webui.core.model.SelectItemOption; import org.exoplatform.webui.ext.filter.UIExtensionFilter; import javax.jcr.*; import javax.portlet.PortletMode; import javax.portlet.PortletPreferences; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; @ComponentConfig( lifecycle = UIApplicationLifecycle.class ) public class UIJCRExplorerPortlet extends UIPortletApplication { /** * Logger. */ private static final Log LOG = ExoLogger.getLogger(UIJCRExplorerPortlet.class.getName()); final static public String ISDIRECTLY_DRIVE = "isDirectlyDrive"; final static public String DRIVE_NAME = "driveName"; final static public String USECASE = "usecase"; final static public String JAILED = "jailed"; final static public String SELECTION = "selection"; final static public String PERSONAL = "personal"; final static public String PARAMETERIZE = "parameterize"; final static public String PARAMETERIZE_PATH = "nodePath"; final static public String SHOW_TOP_BAR = "showTopBar"; final static public String SHOW_ACTION_BAR = "showActionBar"; final static public String SHOW_SIDE_BAR = "showSideBar"; final static public String SHOW_FILTER_BAR = "showFilterBar"; final static private String DOC_NOT_FOUND = "doc-not-found"; private String backTo =""; private boolean flagSelect = false; private Pattern driveParameteriedPathPattern = Pattern.compile(".*\\$\\{(.*)\\}.*"); public UIJCRExplorerPortlet() throws Exception { if (Util.getPortalRequestContext().getRemoteUser() != null) { UIJcrExplorerContainer explorerContainer = addChild(UIJcrExplorerContainer.class, null, null); explorerContainer.initExplorer(); addChild(UIJcrExplorerEditContainer.class, null, null).setRendered(false); } } public boolean isFlagSelect() { return flagSelect; } public void setFlagSelect(boolean flagSelect) { this.flagSelect = flagSelect; } public boolean isShowTopBar() { PortletPreferences portletpref = getPortletPreferences(); return Boolean.valueOf(portletpref.getValue(UIJCRExplorerPortlet.SHOW_TOP_BAR, "false")); } public boolean isShowActionBar() { PortletPreferences portletpref = getPortletPreferences(); return Boolean.valueOf(portletpref.getValue(UIJCRExplorerPortlet.SHOW_ACTION_BAR, "false")) && (!this.findFirstComponentOfType(UIJCRExplorer.class).isAddingDocument() || this.findFirstComponentOfType(UIWorkingArea.class).getChild(UIActionBar.class).hasBackButton()); } public boolean isShowSideBar() { PortletPreferences portletpref = getPortletPreferences(); return Boolean.valueOf(portletpref.getValue(UIJCRExplorerPortlet.SHOW_SIDE_BAR, "false")); } public boolean isShowFilterBar() { PortletPreferences portletpref = getPortletPreferences(); return Boolean.valueOf(portletpref.getValue(UIJCRExplorerPortlet.SHOW_FILTER_BAR, "false")); } public String getBacktoValue() { return backTo; } public void processRender(WebuiApplication app, WebuiRequestContext context) throws Exception { if (Util.getPortalRequestContext().getRemoteUser() == null) { ((PortletRequestContext)context).getWriter().write( String.format("<p style='text-align:center'>%s</p>", context.getApplicationResourceBundle().getString("UIJCRExplorerPortlet.msg.anonymous-access-denied"))); return; } UIJcrExplorerContainer explorerContainer = getChild(UIJcrExplorerContainer.class); UIJcrExplorerEditContainer editContainer = getChild(UIJcrExplorerEditContainer.class); PortletRequestContext portletReqContext = (PortletRequestContext) context ; Map<String, String> map = getElementByContext(context); PortalRequestContext pcontext = Util.getPortalRequestContext(); String backToValue = Util.getPortalRequestContext().getRequestParameter(org.exoplatform.ecm.webui.utils.Utils.URL_BACKTO); if (!portletReqContext.useAjax()) { backTo = backToValue; } HashMap<String, String> changeDrive = (HashMap<String, String>)pcontext.getAttribute("jcrexplorer-show-document"); if (changeDrive!=null) { map = changeDrive; context.setAttribute("jcrexplorer-show-document", null); } if (portletReqContext.getApplicationMode() == PortletMode.VIEW) { if (map.size() > 0) { showDocument(context, map); } else { initwhenDirect(explorerContainer, editContainer); } explorerContainer.setRendered(true); UIJCRExplorer uiExplorer = explorerContainer.getChild(UIJCRExplorer.class); if(uiExplorer != null) { try { uiExplorer.getSession(); try { uiExplorer.getSession().getItem(uiExplorer.getRootPath()); } catch(PathNotFoundException e) { reloadWhenBroken(uiExplorer); super.processRender(app, context); return; } } catch(RepositoryException repo) { super.processRender(app, context); } } getChild(UIJcrExplorerEditContainer.class).setRendered(false); } else if(portletReqContext.getApplicationMode() == PortletMode.HELP) { if (LOG.isDebugEnabled()) LOG.debug("\n\n>>>>>>>>>>>>>>>>>>> IN HELP MODE \n"); } else if(portletReqContext.getApplicationMode() == PortletMode.EDIT) { explorerContainer.setRendered(false); getChild(UIJcrExplorerEditContainer.class).setRendered(true); } // RenderResponse response = context.getResponse(); // Element elementS = response.createElement("script"); // elementS.setAttribute("type", "text/javascript"); // elementS.setAttribute("src", "/eXoWCMResources/javascript/eXo/wcm/backoffice/public/Components.js"); // response.addProperty(MimeResponse.MARKUP_HEAD_ELEMENT,elementS); UIJCRExplorer uiExplorer = explorerContainer.getChild(UIJCRExplorer.class); UITreeExplorer uiTreeExplorer = uiExplorer.findFirstComponentOfType(UITreeExplorer.class); AutoVersionService autoVersionService = WCMCoreUtils.getService(AutoVersionService.class); context.getJavascriptManager(). require("SHARED/multiUpload", "multiUpload").require("SHARED/jquery", "gj") .addScripts("multiUpload.setLocation('" + uiExplorer.getWorkspaceName() + "','" + uiExplorer.getDriveData().getName() + "','" + uiTreeExplorer.getLabel() + "','" + uiExplorer.getCurrentPath() + "','" + org.exoplatform.services.cms.impl.Utils.getPersonalDrivePath(uiExplorer.getDriveData().getHomePath(), ConversationState.getCurrent().getIdentity().getUserId())+ "', '"+ autoVersionService.isVersionSupport(uiExplorer.getCurrentPath(), uiExplorer.getCurrentWorkspace())+"');") .addScripts("gj(document).ready(function() { gj(\"*[rel='tooltip']\").tooltip();});"); super.processRender(app, context); } public void initwhenDirect(UIJcrExplorerContainer explorerContainer, UIJcrExplorerEditContainer editContainer) throws Exception { if (editContainer.getChild(UIJcrExplorerEditForm.class).isFlagSelectRender()) { explorerContainer.initExplorer(); editContainer.getChild(UIJcrExplorerEditForm.class).setFlagSelectRender(false); } } public String getPreferenceRepository() { PortletRequestContext pcontext = (PortletRequestContext)WebuiRequestContext.getCurrentInstance() ; PortletPreferences portletPref = pcontext.getRequest().getPreferences() ; String repository = portletPref.getValue(Utils.REPOSITORY, "") ; return repository ; } public String getPreferenceTrashHomeNodePath() { return getPortletPreferences().getValue(Utils.TRASH_HOME_NODE_PATH, ""); } public String getPreferenceTrashRepository() { return getPortletPreferences().getValue(Utils.TRASH_REPOSITORY, ""); } public String getPreferenceTrashWorkspace() { return getPortletPreferences().getValue(Utils.TRASH_WORKSPACE, ""); } public PortletPreferences getPortletPreferences() { PortletRequestContext pcontext = (PortletRequestContext)WebuiRequestContext.getCurrentInstance(); return pcontext.getRequest().getPreferences(); } public DriveData getUserDrive() throws Exception { ManageDriveService manageDriveService = getApplicationComponent(ManageDriveService.class); String userId = Util.getPortalRequestContext().getRemoteUser(); for(DriveData userDrive : manageDriveService.getPersonalDrives(userId)) { if(userDrive.getHomePath().endsWith("/Private")) { return userDrive; } } return null; } public boolean canUseConfigDrive(String driveName) throws Exception { ManageDriveService dservice = getApplicationComponent(ManageDriveService.class); String userId = Util.getPortalRequestContext().getRemoteUser(); List<String> userRoles = Utils.getMemberships(); for(DriveData drive : dservice.getDriveByUserRoles(userId, userRoles)) { if(drive.getName().equals(driveName)) return true; } return false; } public void reloadWhenBroken(UIJCRExplorer uiExplorer) { uiExplorer.getChild(UIControl.class).setRendered(false); UIWorkingArea uiWorkingArea = uiExplorer.getChild(UIWorkingArea.class); uiWorkingArea.setRenderedChild(UIDrivesArea.class); UIRightClickPopupMenu uiRightClickPopupMenu = uiWorkingArea.getChild(UIRightClickPopupMenu.class); if(uiRightClickPopupMenu!=null) uiRightClickPopupMenu.setRendered(true); } private Map<String, String> getElementByContext(WebuiRequestContext context) { HashMap<String, String> mapParam = new HashMap<>(); //In case access by ajax request if (context.useAjax()) return mapParam; PortalRequestContext pcontext = Util.getPortalRequestContext(); Matcher matcher; Map<String, String[]> requestParams = pcontext.getRequest().getParameterMap(); for(String requestParamName : requestParams.keySet()) { if (requestParamName.equals("path")) { String nodePathParam = pcontext.getRequestParameter("path"); String currentRepo = WCMCoreUtils.getRepository().getConfiguration().getName(); if (nodePathParam != null && nodePathParam.length() > 0) { Pattern patternUrl = Pattern.compile("([^/]+)/(.*)"); matcher = patternUrl.matcher(nodePathParam); if (matcher.find()) { mapParam.put("repository", currentRepo); mapParam.put("drive", matcher.group(1)); mapParam.put("path", matcher.group(2)); } else { patternUrl = Pattern.compile("(.*)"); matcher = patternUrl.matcher(nodePathParam); if (matcher.find()) { mapParam.put("repository", currentRepo); mapParam.put("drive", matcher.group(1)); mapParam.put("path", "/"); } } } } else { mapParam.put(requestParamName, pcontext.getRequest().getParameter(requestParamName)); } } return mapParam; } private void showDocument(WebuiRequestContext context, Map<String, String> map) throws Exception { String repositoryName = String.valueOf(map.get("repository")); String driveName = String.valueOf(map.get("drive")); if (driveName.equals(DOC_NOT_FOUND)) { UIApplication uiApp = findFirstComponentOfType(UIApplication.class); uiApp.addMessage(new ApplicationMessage("UIDrivesArea.msg.not-found", null, ApplicationMessage.WARNING)); return; } String path = String.valueOf(map.get("path")); if (path.indexOf("&") > 0) { path = path.substring(0, path.indexOf("&")); } if(!path.equals("/")) { ArrayList<String> encodeNameArr = new ArrayList<String>(); for(String name : path.split("/")) { if(name.length() > 0) { encodeNameArr.add(Text.escapeIllegalJcrChars(name)); } } StringBuilder encodedPath = new StringBuilder(); for(String encodedName : encodeNameArr) { encodedPath.append("/").append(encodedName); } path = encodedPath.toString(); } UIApplication uiApp = findFirstComponentOfType(UIApplication.class); ManageDriveService manageDrive = getApplicationComponent(ManageDriveService.class); DriveData driveData = null; try { driveData = manageDrive.getDriveByName(driveName); if (driveData == null) throw new PathNotFoundException(); } catch (PathNotFoundException e) { Object[] args = { driveName }; return; } RepositoryService rservice = getApplicationComponent(RepositoryService.class); String userId = Util.getPortalRequestContext().getRemoteUser(); List<String> viewList = new ArrayList<String>(); for (String role : Utils.getMemberships()) { for (String viewName : driveData.getViews().split(",")) { if (!viewList.contains(viewName.trim())) { Node viewNode = getApplicationComponent(ManageViewService.class).getViewByName(viewName.trim(), WCMCoreUtils.getSystemSessionProvider()); String permiss = viewNode.getProperty("exo:accessPermissions").getString(); if (permiss.contains("${userId}")) permiss = permiss.replace("${userId}", userId); String[] viewPermissions = permiss.split(","); if (permiss.equals("*")) viewList.add(viewName.trim()); if (driveData.hasPermission(viewPermissions, role)) viewList.add(viewName.trim()); } } } StringBuffer viewListStr = new StringBuffer(); List<SelectItemOption<String>> viewOptions = new ArrayList<SelectItemOption<String>>(); ResourceBundle res = context.getApplicationResourceBundle(); String viewLabel = null; for (String viewName : viewList) { try { viewLabel = res.getString("Views.label." + viewName); } catch (MissingResourceException e) { viewLabel = viewName; } viewOptions.add(new SelectItemOption<String>(viewLabel, viewName)); if (viewListStr.length() > 0) viewListStr.append(",").append(viewName); else viewListStr.append(viewName); } driveData.setViews(viewListStr.toString()); String homePath = driveData.getHomePath(); Matcher matcher = driveParameteriedPathPattern.matcher(homePath); if(matcher.matches()) { // if the drive is a virtual drive containing, the paramterized value is available as request parameter String drivePathParamName = matcher.group(1); String drivePathParamValue = map.get(drivePathParamName); driveData.getParameters().put(drivePathParamName, drivePathParamValue); // we need to get the real drive home path if(StringUtils.isNotEmpty(drivePathParamValue)) { if(ManageDriveServiceImpl.DRIVE_PARAMATER_USER_ID.equals(drivePathParamName)) { // User id parameter is a special case since it must be replaced by its distributed format homePath = org.exoplatform.services.cms.impl.Utils.getPersonalDrivePath(homePath, drivePathParamValue); } else { // we update the drive homePath with the real value homePath = StringUtils.replaceOnce(homePath, "${" + drivePathParamName + "}", drivePathParamValue); } } } // we extract the absolute path of the file (remove the drive name) String contentRealPath = path; int firstSlash = path.indexOf("/"); if(firstSlash >= 0) { contentRealPath = path.substring(firstSlash); } setFlagSelect(true); UIJCRExplorer uiExplorer = findFirstComponentOfType(UIJCRExplorer.class); uiExplorer.setDriveData(driveData); uiExplorer.setIsReferenceNode(false); try { Session session = WCMCoreUtils.getUserSessionProvider().getSession(driveData.getWorkspace(), rservice.getCurrentRepository()); // check if it exists // we assume that the path is a real path session.getItem(contentRealPath); } catch(AccessDeniedException ace) { Object[] args = { driveName }; uiApp.addMessage(new ApplicationMessage("UIDrivesArea.msg.access-denied", args, ApplicationMessage.WARNING)); return; } catch(NoSuchWorkspaceException nosuchWS) { Object[] args = { driveName }; uiApp.addMessage(new ApplicationMessage("UIDrivesArea.msg.workspace-not-exist", args, ApplicationMessage.WARNING)); return; } catch(Exception e) { JCRExceptionManager.process(uiApp, e); return; } uiExplorer.setRepositoryName(repositoryName); uiExplorer.setWorkspaceName(driveData.getWorkspace()); uiExplorer.setRootPath(homePath); String addressPath = contentRealPath.replaceAll("/+", "/"); // handle special case of docs in Public Personal Documents and the symlink "Public" if(driveData.getName().equals(ManageDriveServiceImpl.PERSONAL_DRIVE_NAME) && !addressPath.startsWith(homePath)) { String publicHomePath = homePath.replace("/" + ManageDriveServiceImpl.PERSONAL_DRIVE_PRIVATE_FOLDER_NAME, "/" + ManageDriveServiceImpl.PERSONAL_DRIVE_PUBLIC_FOLDER_NAME); if(addressPath.startsWith(publicHomePath)) { addressPath = addressPath.replace("/" + ManageDriveServiceImpl.PERSONAL_DRIVE_PUBLIC_FOLDER_NAME, "/Private/" + ManageDriveServiceImpl.PERSONAL_DRIVE_PUBLIC_FOLDER_NAME); } } Preference pref = uiExplorer.getPreference(); pref.setShowSideBar(driveData.getViewSideBar()); pref.setShowNonDocumentType(driveData.getViewNonDocument()); pref.setShowPreferenceDocuments(driveData.getViewPreferences()); pref.setAllowCreateFoder(driveData.getAllowCreateFolders()); pref.setShowHiddenNode(driveData.getShowHiddenNode()); uiExplorer.setIsReferenceNode(false); UIControl uiControl = uiExplorer.getChild(UIControl.class); UIAddressBar uiAddressBar = uiControl.getChild(UIAddressBar.class); uiAddressBar.setViewList(viewList); uiAddressBar.setSelectedViewName(viewList.get(0)); uiAddressBar.setRendered(isShowTopBar()); UIWorkingArea uiWorkingArea = findFirstComponentOfType(UIWorkingArea.class); UIActionBar uiActionbar = uiWorkingArea.getChild(UIActionBar.class); boolean isShowActionBar = isShowActionBar() ; uiActionbar.setTabOptions(viewList.get(0)); uiActionbar.setRendered(isShowActionBar); uiExplorer.clearNodeHistory(addressPath); uiExplorer.setSelectNode(driveData.getWorkspace(), addressPath, homePath); UIDocumentWorkspace uiDocWorkspace = uiWorkingArea.getChild(UIDocumentWorkspace.class); uiDocWorkspace.setRenderedChild(UIDocumentContainer.class); uiDocWorkspace.setRendered(true); UIDrivesArea uiDrive = uiWorkingArea.getChild(UIDrivesArea.class); if (uiDrive != null) uiDrive.setRendered(false); context.addUIComponentToUpdateByAjax(uiDocWorkspace); UIPopupContainer popupAction = getChild(UIPopupContainer.class); if (popupAction != null && popupAction.isRendered()) { popupAction.deActivate(); context.addUIComponentToUpdateByAjax(popupAction); } Boolean isEdit = Boolean.valueOf(Util.getPortalRequestContext().getRequestParameter("edit")); Node selectedNode = uiExplorer.getCurrentNode(); if (isEdit) { if (uiExplorer.getCurrentPath().equals(addressPath)) { if(canManageNode(selectedNode, uiApp, uiExplorer, uiActionbar, context, EditDocumentActionComponent.getFilters())) { EditDocumentActionComponent.editDocument(null, context, this, uiExplorer, selectedNode, uiApp); }else if(canManageNode(selectedNode, uiApp, uiExplorer, uiActionbar, context, EditPropertyActionComponent.getFilters())) { EditPropertyActionComponent.editDocument(null, context, this, uiExplorer, selectedNode, uiApp); } } else { uiApp.addMessage(new ApplicationMessage("UIJCRExplorerPortlet.msg.file-access-denied", null, ApplicationMessage.WARNING)); } } boolean isAddNew = Boolean.valueOf(Util.getPortalRequestContext().getRequestParameter("addNew")); if (!isEdit && isAddNew) { if (canManageNode(selectedNode, uiApp, uiExplorer, uiActionbar, context, AddDocumentActionComponent.getFilters())) { AddDocumentActionComponent.addDocument(null, uiExplorer, uiApp, this, context); } else { uiApp.addMessage(new ApplicationMessage("UIJCRExplorerPortlet.msg.file-access-denied", null, ApplicationMessage.WARNING)); } } uiExplorer.refreshExplorer(null, (isAddNew && isEdit)); } private boolean canManageNode(Node selectedNode, UIApplication uiApp, UIJCRExplorer uiExplorer, UIActionBar uiActionBar, Object context, List<UIExtensionFilter> filters) throws Exception { Map<String, Object> ctx = new HashMap<String, Object>(); ctx.put(UIActionBar.class.getName(), uiActionBar); ctx.put(UIJCRExplorer.class.getName(), uiExplorer); ctx.put(UIApplication.class.getName(), uiApp); ctx.put(Node.class.getName(), selectedNode); ctx.put(WebuiRequestContext.class.getName(), context); for (UIExtensionFilter filter : filters) try { if (!filter.accept(ctx)) return false; } catch (Exception e) { return false; } return true; } }